# Uptimeify Documentation — Full Export > Expanded, text-first export of the Uptimeify documentation with page content. Compact index: https://docs.uptimeify.io/llms.txt ## Overview ### Welcome to Uptimeify URL: https://docs.uptimeify.io Description: White-label uptime, SSL & synthetic monitoring for agencies — hosted in the EU. Summary: Uptimeify is a **white-label monitoring platform for agencies and MSPs**. Watch your clients' websites and infrastructure, alert the right people the moment something breaks, and give every client a branded status page and automated report — all under your own brand, hosted in the EU. ## What you can monitor From a single dashboard you can run: - **Websites** — uptime, SSL certificate, response time, keyword presence, page size, and HTTPS-redirect checks. - **Servers & services** — DNS, ICMP (ping), SSH, FTP, SMTP, IMAP/POP, DNSBL blacklist and domain-expiry checks. - **Synthetic & scheduled** — multi-step browser flows with Playwright, and Heartbeat (cron) checks for background jobs. See [Monitoring](/monitoring) for every check type and how to tune intervals, thresholds and locations. ## Alerting that doesn't cry wolf Every failure is confirmed from **multiple EU locations** before an incident opens, so you alert on real outages — not network blips. Route alerts to **29 notification channels** (Slack, Microsoft Teams, PagerDuty, Opsgenie, SMS, email, webhooks and more) with multi-step, time-based escalation so an unacknowledged alert moves to the next responder. Learn how detection works in [Incidents](/incidents), and wire up channels in [Integrations](/integrations). ## Client-facing, under your brand - **Status pages** — branded, public or password-protected, on your own custom domain. See [Status Pages](/status-pages). - **Automated PDF reports** — with your logo, to justify recurring fees. - **Maintenance windows** — suppress alerts during planned work. See [Maintenance](/maintenance). ## Built for agencies Unlimited sub-accounts per client, margin control on care plans, and a full **REST API** to automate customers, monitors, status pages and notification channels. Start with the [API Documentation](/api). ## Pick a topic Set up website, uptime, SSL, and synthetic monitors and tune their checks. Publish branded, public or password-protected status pages for your clients. Understand how incidents are detected, confirmed, and resolved. Schedule maintenance windows to suppress alerts during planned work. Connect Slack, webhooks, and other notification channels. Automate everything with the REST API — customers, monitors, status pages. ## API Reference ### API Documentation URL: https://docs.uptimeify.io/api Description: Overview of the REST API. Select a resource from the left. Summary: ## AI / LLM Text Exports - [LLMS index for AI agents](https://uptimeify.io/llms) - [LLMS full reference for AI ingestion](https://uptimeify.io/llms-full) - [German LLMS index for AI agents](https://uptimeify.io/de/llms) - [German LLMS full reference for AI ingestion](https://uptimeify.io/de/llms-full) ## Base URL All examples use a placeholder base URL: ```bash BASE_URL="https://uptimeify.io" ``` ## Authentication Most endpoints require authentication. ```bash TOKEN="wsm_" curl -H "Authorization: Bearer $TOKEN" "$BASE_URL/api/websites" ``` API tokens generated in the dashboard always start with `wsm_`. Make sure you include the full token (including the prefix), otherwise the API will return `401 Unauthorized`. ## UUID Path Parameters For migrated resources, path parameters use the resource `publicId` UUID in the docs and examples. - Use UUIDs for endpoint paths such as `/api/websites/:websitePublicId`, `/api/customers/:customerPublicId`, `/api/organizations/:organizationPublicId`, `/api/incidents/:incidentPublicId`, `/api/customer-ips/:customerIpPublicId`, `/api/customer-domains/:customerDomainPublicId`, and monitor-specific `:...PublicId` parameters. - Internal numeric `id` fields may still appear in response payloads for internal references. - Query/body fields like `customerId`, `websiteId`, or `organizationId` stay numeric unless the endpoint page explicitly says otherwise. ## Responses and Errors - `2xx` indicates success - `4xx` indicates a request/auth problem - `5xx` indicates a server error - [Error codes and known API pitfalls](./error-codes-and-known-pitfalls) Example error response: ```json { "statusCode": 401, "statusMessage": "Unauthorized" } ``` ### Global Administration URL: https://docs.uptimeify.io/api/admin Description: This section covers the global administration endpoints, which are protected and only accessible to platform administrators. Summary: *(Endpoints are still being documented)* ## Endpoints ### API Tokens URL: https://docs.uptimeify.io/api/api-tokens Description: API tokens allow programmatic access to the Uptimeify API. Tokens are prefixed with wsm_ and can be scoped to a specific customer or organization-wide. Summary: There are two endpoint scopes: - **Organization tokens** (`/api/organization/tokens`) — admin-only, full org access - **Customer tokens** (`/api/customer/tokens`) — scoped to accessible customers ## Authentication All examples assume a session cookie (not API tokens — API tokens cannot manage other API tokens): ```bash BASE_URL="https://uptimeify.io" ``` ## Endpoints - [List Organization Tokens](./list-organization-tokens) - [Create Organization Token](./create-organization-token) - [Delete Organization Token](./delete-organization-token) - [List Customer Tokens](./list-customer-tokens) - [Create Customer Token](./create-customer-token) - [Delete Customer Token](./delete-customer-token) ### Create Customer Token URL: https://docs.uptimeify.io/api/api-tokens/create-customer-token Description: Creates a new API token scoped to a customer. Restricted users must specify customerId. The full token is returned only once — store it securely. Summary: `POST /api/customer/tokens` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `name` | string | Yes | — | Token display name (1–255 chars) | | `expiresInDays` | number | No | null | Days until expiration (1–365). Null = no expiration. | | `customerId` | number | No* | null | Scope token to a specific customer. Required for restricted users. | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/customer/tokens" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Corp API Token", "customerId": 5, "expiresInDays": 180 }' ``` ## Response ```json { "id": 2, "name": "Acme Corp API Token", "token": "wsm_f7e6d5c4b3a2...", "lastUsedAt": null, "expiresAt": "2026-10-15T08:00:00.000Z", "createdAt": "2026-04-15T08:00:00.000Z" } ``` ## Common errors - `400 Invalid customer ID` when customerId doesn't belong to your organization - `400 customerId is required` when restricted user doesn't specify customerId - `403 Forbidden` when customer is outside user's scope ### Create Organization Token URL: https://docs.uptimeify.io/api/api-tokens/create-organization-token Description: Creates a new API token. The full token is returned only once — store it securely. Requires admin role. Summary: `POST /api/organization/tokens` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `name` | string | Yes | — | Token display name (1–255 chars) | | `expiresInDays` | number | No | null | Days until expiration (1–365). Null = no expiration. | | `customerId` | number | No | null | Scope token to a specific customer (must belong to your org) | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/organization/tokens" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "name": "Production API", "expiresInDays": 90 }' ``` ## Response ```json { "id": 1, "name": "Production API", "token": "wsm_a1b2c3d4e5f6...", "lastUsedAt": null, "expiresAt": "2026-07-15T10:00:00.000Z", "createdAt": "2026-04-15T10:00:00.000Z" } ``` ## Common errors - `400 Invalid customer ID` when customerId doesn't belong to your organization - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin ### Delete Customer Token URL: https://docs.uptimeify.io/api/api-tokens/delete-customer-token Description: Permanently revokes a customer-scoped API token. Users can only delete tokens within their customer scope. Summary: `DELETE /api/customer/tokens/:id` ## Example (cURL) ```bash curl -X DELETE "$BASE_URL/api/customer/tokens/2" \ -H "Cookie: $SESSION_COOKIE" ``` ## Response ```json { "success": true } ``` ## Common errors - `403 Forbidden` when the token is outside your customer scope, or when the token is org-scoped (no `customerId`) - `404 Token not found` when the token doesn't exist or belongs to another org ### Delete Organization Token URL: https://docs.uptimeify.io/api/api-tokens/delete-organization-token Description: Permanently revokes an API token. Requires admin role. Summary: `DELETE /api/organization/tokens/:id` ## Example (cURL) ```bash curl -X DELETE "$BASE_URL/api/organization/tokens/1" \ -H "Cookie: $SESSION_COOKIE" ``` ## Response ```json { "success": true } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `404 Token not found` when the token doesn't exist or belongs to another org ### List Customer Tokens URL: https://docs.uptimeify.io/api/api-tokens/list-customer-tokens Description: Returns API tokens visible to the current user. Restricted users see only their customer-scoped tokens; admins see all tokens. Tokens are masked — only the first 8 characters are shown. Summary: `GET /api/customer/tokens` ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/customer/tokens" \ -H "Cookie: $SESSION_COOKIE" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": 2, "organizationId": 1, "name": "Customer Scoped Token", "customerId": 5, "customerName": "Acme Corp", "lastUsedAt": null, "expiresAt": null, "createdAt": "2026-02-01T08:00:00.000Z", "tokenHint": "wsm_f7e6d5..." } ] ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when user lacks read access ### List Organization Tokens URL: https://docs.uptimeify.io/api/api-tokens/list-organization-tokens Description: Returns all API tokens for the organization. Tokens are masked — only the first 8 characters are shown. Requires admin role. Summary: `GET /api/organization/tokens` ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/organization/tokens" \ -H "Cookie: $SESSION_COOKIE" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": 1, "organizationId": 1, "name": "Production API", "customerId": null, "customerName": null, "lastUsedAt": "2026-04-01T12:00:00.000Z", "expiresAt": null, "createdAt": "2026-01-15T10:00:00.000Z", "tokenHint": "wsm_a1b2c..." } ] ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin ### Auth & Session URL: https://docs.uptimeify.io/api/auth Description: Manage your current user session and retrieve profile information. Summary: ## Endpoints - [Get Current User](./get-current-user) ### Get Current User URL: https://docs.uptimeify.io/api/auth/get-current-user Description: Returns a reduced view of the currently authenticated user and their session. Summary: `GET /api/auth/get-session` ## Request ```http GET /api/auth/get-session HTTP/1.1 ``` This endpoint returns a public-safe session payload. For integrations, use API tokens (`Authorization: Bearer wsm_...`) with the REST endpoints under `/api/**`. Sensitive internal app fields such as `email`, `role`, `language`, `isGlobalAdmin`, `isGlobalSupporter`, `emailVerified`, `image`, and platform-admin customer context are intentionally not included. ## Response ```json { "user": { "id": "user_12345", "name": "Max Mustermann", "firstName": "Max", "lastName": "Mustermann", "organizationId": 1, "organizationStatus": "active", "isActive": true, "createdAt": "2026-03-31T15:50:49.030Z", "updatedAt": "2026-03-31T15:50:49.030Z" }, "session": { "userId": "user_12345", "expiresAt": "2027-03-31T15:58:26.618Z", "token": "session-token-value" } } ``` ### Change Requests URL: https://docs.uptimeify.io/api/change-requests Description: How customers request changes to managed monitors and how organizations resolve them. Summary: Monitors with `managementType: managed` are read-only for customer-scoped users (see [Managed vs. Self-Service Monitors](/monitoring/managed-vs-self-service)). Instead of editing directly, a customer opens a **change request** against the monitor; the organization reviews it in its inbox and accepts or rejects it. A change request has a `kind`: | Kind | Meaning | Effect on accept | |---|---|---| | `change` | Free-text change wish for a managed monitor | None automatic — the org applies the change manually | | `request_managed` | The customer asks the org to take over responsibility for a monitor | The monitor is flipped to `managed` automatically | Endpoints: - [Create Change Request](/api/change-requests/create-change-request) — `POST /api/monitors/:monitorType/:monitorId/change-requests` (customer or org) - [List Change Requests](/api/change-requests/list-change-requests) — `GET /api/change-requests` (org admins) - [Resolve Change Request](/api/change-requests/resolve-change-request) — `PATCH /api/change-requests/:id` (org admins) Open requests are limited to **10 per customer** across all monitor types; further creates return `429` (`tooManyOpenRequests`). ### Create Change Request URL: https://docs.uptimeify.io/api/change-requests/create-change-request Description: Opens a change request against any monitor (all monitor types). Summary: `POST /api/monitors/:monitorType/:monitorId/change-requests` Read access to the monitor is sufficient — the typical caller is a customer portal user who *lacks* write access to a `managed` monitor. ## Path parameters | Parameter | Description | |---|---| | `monitorType` | One of `website`, `dns`, `icmp`, `smtp`, `ssh`, `ftp`, `imap_pop`, `domain`, `dnsbl` | | `monitorId` | Numeric ID of the monitor | ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `kind` | string | No | `change` | `change` (free-text wish) or `request_managed` (ask the org to take the monitor over) | | `message` | string | Yes | — | The request text (1–2000 chars) | ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST "$BASE_URL/api/monitors/website/103/change-requests" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "kind": "change", "message": "Please lower the check interval to 1 minute." }' ``` ## Response ```json { "id": 12, "status": "open" } ``` ## Common errors - `400 Invalid monitor type` (`invalidMonitorType`) when `monitorType` is not one of the supported types - `400 Invalid monitor identifier` when `monitorId` is not a positive integer - `401 Unauthorized` when you are not logged in - `403 Forbidden` / `404 Not found` when the monitor is outside your scope - `429 Too many open requests` (`tooManyOpenRequests`) when the customer already has 10 open requests ### List Change Requests URL: https://docs.uptimeify.io/api/change-requests/list-change-requests Description: Lists the organization's change-request inbox. Summary: `GET /api/change-requests` Organization write access required (organization admin or global admin). Results are strictly scoped to the caller's organization. ## Query parameters | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `status` | string | No | `open` | `open`, `accepted`, or `rejected` | ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl "$BASE_URL/api/change-requests?status=open" \ -H "Authorization: Bearer $TOKEN" ``` ## Response Newest first. `monitorName` is resolved per monitor type; `websiteId` is a legacy field populated only for website monitors. ```json [ { "id": 12, "monitorType": "website", "monitorId": 103, "websiteId": 103, "customerId": 101, "customerName": "Customer A GmbH", "monitorName": "New Landing Page", "requestedBy": "usr_123", "kind": "change", "message": "Please lower the check interval to 1 minute.", "status": "open", "resolvedBy": null, "resolvedAt": null, "createdAt": "2026-07-09T10:00:00.000Z" } ] ``` ## Common errors - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you are not an organization admin ### Resolve Change Request URL: https://docs.uptimeify.io/api/change-requests/resolve-change-request Description: Accepts or rejects an open change request. Summary: `PATCH /api/change-requests/:id` Organization write access required. The status transition is atomic — under concurrent resolves only one caller wins; the loser receives `409`. Accepting a request with `kind: request_managed` additionally flips the target monitor to `managementType: managed` (dispatched to the correct table for the monitor's type). ## Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `status` | string | Yes | `accepted` or `rejected` | ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/change-requests/12" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "status": "accepted" }' ``` ## Response ```json { "id": 12, "status": "accepted" } ``` ## Common errors - `400 Invalid change-request identifier` - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you are not an organization admin - `404 Change request not found` - `409 Change request already resolved` when the request is no longer `open` ### Custom Fields URL: https://docs.uptimeify.io/api/custom-fields Description: Define custom metadata fields that can be attached to customers and websites. Custom fields support text, select, and multi-select types. Summary: ## Authentication All examples assume a bearer token: ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Endpoints - [List Custom Fields](./list-custom-fields) - [Create Custom Field](./create-custom-field) - [Update Custom Field](./update-custom-field) - [Delete Custom Field](./delete-custom-field) ### Create Custom Field URL: https://docs.uptimeify.io/api/custom-fields/create-custom-field Description: Creates a new custom field definition. Summary: `POST /api/custom-fields` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `organizationId` | number | Yes | — | Organization ID | | `name` | string | Yes | — | Display name | | `fieldKey` | string | No | auto from name | Unique key (auto-normalized: lowercase, non-alphanumeric → `_`) | | `fieldType` | string | No | `text` | `text`, `select`, or `multiselect` | | `isRequired` | boolean | No | false | Whether the field is required | | `displayOrder` | number | No | 0 | Sort order | | `options` | array | No | `[]` | Options for select/multiselect types | | `placeholder` | string\|null | No | null | Placeholder text | | `helpText` | string\|null | No | null | Help text below the field | | `showInTable` | boolean | No | true | Show in table views | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/custom-fields" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "organizationId": 1, "name": "Environment", "fieldType": "select", "options": ["production", "staging", "development"], "isRequired": true, "showInTable": true }' ``` ## Common errors - `409 Conflict` when `fieldKey` already exists for the organization ## Response Returns the created custom field object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Delete Custom Field URL: https://docs.uptimeify.io/api/custom-fields/delete-custom-field Description: Soft-deletes a custom field (sets isActive: false). Summary: `DELETE /api/custom-fields/:id` ## Example (cURL) ```bash curl -X DELETE "$BASE_URL/api/custom-fields/1" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true, "message": "Custom field deleted successfully" } ``` ### List Custom Fields URL: https://docs.uptimeify.io/api/custom-fields/list-custom-fields Description: Returns all active custom field definitions for the organization. Summary: `GET /api/custom-fields` ## Query Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `organizationId` | number | session org | Override organization scope | ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/custom-fields" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": 1, "organizationId": 1, "name": "Data Center", "fieldKey": "data_center", "fieldType": "text", "isRequired": false, "displayOrder": 0, "options": [], "placeholder": "e.g. fsn1", "helpText": "Primary data center location", "showInTable": true, "isActive": true, "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-01-01T00:00:00.000Z" } ] ``` Only active fields (`isActive: true`) are returned, ordered by `displayOrder`. ### Update Custom Field URL: https://docs.uptimeify.io/api/custom-fields/update-custom-field Description: Updates a custom field definition. All fields are optional. Summary: `PATCH /api/custom-fields/:id` ## Request Body (all optional) | Field | Type | Description | |-------|------|-------------| | `name` | string | Display name | | `fieldType` | string | `text`, `select`, or `multiselect` | | `isRequired` | boolean | Whether the field is required | | `displayOrder` | number | Sort order | | `options` | array | Options for select/multiselect | | `placeholder` | string\|null | Placeholder text | | `helpText` | string\|null | Help text | | `showInTable` | boolean | Show in table views | | `isActive` | boolean | Soft delete (set to false) | ## Example (cURL) ```bash curl -X PATCH "$BASE_URL/api/custom-fields/1" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Environment", "options": ["production", "staging", "development", "qa"] }' ``` ## Response Returns the updated custom field object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Customer Management URL: https://docs.uptimeify.io/api/customers Description: Path-based customer endpoints use customerPublicId UUIDs. Summary: ## Endpoints - [List Customers](./list-customers) - [Create Customer](./create-customer) - [Get Customer Details](./get-customer-details) - [Update Customer](./update-customer) - [Change Package](./change-package) - [SMS Usage](./sms-usage) ### Change Package URL: https://docs.uptimeify.io/api/customers/change-package Description: Changes the customer's package assignment. Summary: `PATCH /api/customers/:customerPublicId` This uses the same endpoint as [Update Customer](./update-customer) — you usually send `packageId`. Legacy `packageType` values are still accepted for backward compatibility. ## Authentication ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Request Body ```json { "packageId": 12 } ``` ## Example Request ```bash curl -X PATCH "$BASE_URL/api/customers/6bfec6f6-245a-47ce-843b-157d97d56f88" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "packageId": 12 }' ``` ## Example Response ```json { "id": 101, "publicId": "6bfec6f6-245a-47ce-843b-157d97d56f88", "organizationId": 1, "name": "Customer A GmbH", "email": "contact@customer-a.de", "notificationPhoneNumber": null, "notificationEmail": null, "packageId": 12, "status": "active", "monthlyReportsEnabled": true, "customFields": {}, "notificationChannels": null, "notificationTargets": null, "updatedAt": "2026-02-26T19:37:00.000Z" } ``` ## Common Errors - `400` Invalid Customer identifier - `401` Unauthorized - `403` Forbidden / Organization ID not found - `404` Customer not found - `500` Failed to update customer ### Create Customer URL: https://docs.uptimeify.io/api/customers/create-customer Description: Creates a new customer and assigns an organization-defined package via packageType. Summary: `POST /api/customers` ## Authentication This endpoint requires authentication. ```bash BASE_URL="https://uptimeify.io" TOKEN="wsm_" ``` ## Request Body ```json { "name": "Customer Name", "email": "customer@example.com", "packageType": "business", // use the configured packageType or displayName for the organization "organizationId": 1, // optional (required only for global admins) "status": "active", // optional, Default: active "customFields": { ... } // optional } ``` Notes: - `packageType` can contain the configured package key or the package display name of the organization. Known aliases such as `aquisition_test` are normalized automatically. - If no configured package matches, the request is rejected with `400 Bad Request`. - For non-global-admin users, `organizationId` is derived from your session/token and must not be overridden. - For global admins, `organizationId` must be provided explicitly. ## Ownership & permission overrides (optional) These fields control the customer's [managed vs. self-service](/monitoring/managed-vs-self-service) permissions and channel-type policy. They are **organization-write gated**: only organization admins (or global admins) can set them — a non-admin caller's values are ignored and the schema defaults apply. `null` (or omitting the field) means *inherit from the customer's package config*. | Field | Type | Default | Description | |-------|------|---------|-------------| | `allowSelfService` | boolean\|null | null (inherit) | Whether the customer may create and manage `self_service` monitors | | `maxSelfServiceUrls` | number\|null | null (inherit) | Cap on the customer's **total** `self_service` monitors across all monitor types | | `canEditManaged` | boolean | false | Exception: lets this customer edit `managed` monitors (class flips stay org-only). Grants are written to the audit log. | | `enableEmailAlerts` | boolean\|null | null (inherit) | Channel-type policy override — email alerts | | `enableSmsAlerts` | boolean\|null | null (inherit) | Channel-type policy override — SMS alerts | | `enableWebhookAlerts` | boolean\|null | null (inherit) | Channel-type policy override — webhooks | | `enableIntegrationAlerts` | boolean\|null | null (inherit) | Channel-type policy override — integrations | | `enablePostRequestEscalation` | boolean\|null | null (inherit) | Channel-type policy override — POST-request escalation | The legacy `notificationChannels` JSONB override is deprecated: channel-type policy lives in the `enable*` fields above. ## Response ```json { "success": true, "customer": { "id": 64, "publicId": "6d74c32b-a97c-49b9-be3e-2b5e24bed826", "organizationId": 2, "name": "Example Customer", "email": "example@test.com", "notificationPhoneNumber": null, "notificationEmail": null, "packageId": 7, "packageType": "essential", "status": "active", "allowedCheckCountryCodes": null, "cancellationDate": null, "cancelledAt": null, "customFields": { "region": "EU", "planOwner": "Operations" }, "monthlyReportsEnabled": true, "notificationChannels": null, "notificationTargets": null, "notificationRules": null, "smsUsageCurrentMonth": 0, "createdAt": "2026-04-04T12:27:13.415Z", "updatedAt": "2026-04-04T12:27:13.415Z" } } ``` ### Get Customer Details URL: https://docs.uptimeify.io/api/customers/get-customer-details Description: Returns details of a specific customer. Summary: `GET /api/customers/:customerPublicId` `packageDisplayName` is the configured display label of the assigned organization package. It is not a normalized global enum and may contain organization-specific names such as `aquisition_test`. ## Response ```json { "id": 101, "publicId": "6bfec6f6-245a-47ce-843b-157d97d56f88", "organizationId": 1, "name": "Customer A GmbH", "email": "contact@customer-a.de", "notificationPhoneNumber": "+491701234567", "notificationEmail": "alerts@customer-a.de", "packageId": 3, "packageDisplayName": "Growth", "status": "active", "customFields": { "internalReference": "KD-999" }, "monthlyReportsEnabled": true, "notificationChannels": null, "notificationTargets": null, "notificationRules": null, "smsUsageCurrentMonth": 0, "updatedAt": "2023-05-15T10:00:00Z", "createdAt": "2023-05-15T10:00:00Z" } ``` ## Common Errors - `400` Invalid Customer identifier - `401` Unauthorized - `403` Forbidden / Organization ID not found - `404` Customer not found ### List Customers URL: https://docs.uptimeify.io/api/customers/list-customers Description: Lists all customers of the organization. Summary: `GET /api/customers` ## Query Parameters - `organizationId` (required): The ID of the organization. - `fields` (optional): Set to `minimal` to return a lightweight shape containing only `id`, `publicId`, `name`, `status`, and `customFields` — the monitor counts and package details are omitted, and the response is much smaller. Useful for populating pickers/dropdowns. ## Response With `fields=minimal`: ```json [ { "id": 101, "publicId": "cus_9f3a…", "name": "Customer A GmbH", "status": "active", "customFields": { "region": "EU" } } ] ``` Default response: ```json [ { "id": 101, "organizationId": 1, "name": "Customer A GmbH", "email": "contact@customer-a.de", "packageId": 4, "packageDisplayName": "Business", "status": "active", "cancellationDate": null, "notificationEmail": "alerts@customer-a.de", "createdAt": "2023-05-15T10:00:00Z" }, { "id": 102, "organizationId": 1, "name": "StartUp XY", "email": "info@startup-xy.com", "packageId": 1, "packageDisplayName": "Essential", "status": "marked_for_cancellation", "cancellationDate": "2024-12-31T23:59:59Z", "createdAt": "2023-06-20T14:30:00Z" } ] ``` Note: The list response intentionally no longer exposes the raw `packageType`. Use `packageDisplayName` for display and `packageId` for technical mapping. `packageDisplayName` comes from the assigned organization package config and may therefore be organization-specific. ### SMS Usage URL: https://docs.uptimeify.io/api/customers/sms-usage Description: Returns the SMS usage for the current calendar month across all customers of the organization, sorted by usage descending. Summary: `GET /api/customers/sms-usage` ## Query Parameters - `organizationId` (required): The ID of the organization. ## Response ```json { "total": 47, "customers": [ { "publicId": "6bfec6f6-245a-47ce-843b-157d97d56f88", "name": "Customer A GmbH", "status": "active", "smsUsageCurrentMonth": 32 }, { "publicId": "9a1c3d2e-8f4b-42a1-b7c9-3e5f12d84a90", "name": "StartUp XY", "status": "active", "smsUsageCurrentMonth": 15 }, { "publicId": "2d7e5f1a-6c3b-4d9e-a2f8-1b4c7e9d3a56", "name": "Inactive Corp", "status": "inactive", "smsUsageCurrentMonth": 0 } ] } ``` ### Fields | Field | Type | Description | |---|---|---| | `total` | `number` | Sum of `smsUsageCurrentMonth` across all returned customers. | | `customers[].publicId` | `string` | Customer UUID. | | `customers[].name` | `string` | Customer display name. | | `customers[].status` | `string` | Customer status: `active`, `inactive`, `marked_for_cancellation`, or `cancelled`. | | `customers[].smsUsageCurrentMonth` | `number` | Number of SMS sent for this customer in the current month. Resets at the start of each calendar month. | ## Notes - The usage counter `smsUsageCurrentMonth` resets at the beginning of each calendar month. - Customers with zero usage are included in the response. - Results are ordered by `smsUsageCurrentMonth` descending (highest usage first). - For the complete SMS quota and overage details of the entire organization, see the billing overview. ## Common Errors - `400` Organization ID required - `401` Unauthorized - `403` Forbidden ### Update Customer URL: https://docs.uptimeify.io/api/customers/update-customer Description: Updates customer details. Summary: `PATCH /api/customers/:customerPublicId` ## Authentication ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Request Body All fields are optional. Omitted fields keep their current values. ```json { "name": "New Name", "email": "new@example.com", "status": "active", "packageType": "business", // configured packageType or displayName for the organization "notificationEmail": "alerts@customer-a.de", "notificationPhoneNumber": "+491701234567", "monthlyReportsEnabled": true, "customFields": { "internalReference": "KD-999" } } ``` Notes: - `packageType` can contain the configured package key or the package display name of the organization. Known aliases such as `aquisition_test` are normalized automatically. ## Ownership & permission overrides (optional) These fields control the customer's [managed vs. self-service](/monitoring/managed-vs-self-service) permissions and channel-type policy. They are **organization-write gated**: a customer-scoped caller's writes to these fields are silently ignored server-side. `null` means *inherit from the customer's package config*. | Field | Type | Default | Description | |-------|------|---------|-------------| | `allowSelfService` | boolean\|null | null (inherit) | Whether the customer may create and manage `self_service` monitors | | `maxSelfServiceUrls` | number\|null | null (inherit) | Cap on the customer's **total** `self_service` monitors across all monitor types | | `canEditManaged` | boolean | false | Exception: lets this customer edit `managed` monitors (class flips stay org-only). Changes are written to the audit log. | | `enableEmailAlerts` | boolean\|null | null (inherit) | Channel-type policy override — email alerts | | `enableSmsAlerts` | boolean\|null | null (inherit) | Channel-type policy override — SMS alerts | | `enableWebhookAlerts` | boolean\|null | null (inherit) | Channel-type policy override — webhooks | | `enableIntegrationAlerts` | boolean\|null | null (inherit) | Channel-type policy override — integrations | | `enablePostRequestEscalation` | boolean\|null | null (inherit) | Channel-type policy override — POST-request escalation | The legacy `notificationChannels` JSONB override is deprecated: channel-type policy lives in the `enable*` fields above. ## Example Request ```bash curl -X PATCH "$BASE_URL/api/customers/6bfec6f6-245a-47ce-843b-157d97d56f88" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Customer A GmbH (Updated)", "monthlyReportsEnabled": true }' ``` ## Example Response ```json { "id": 101, "publicId": "6bfec6f6-245a-47ce-843b-157d97d56f88", "organizationId": 1, "name": "Customer A GmbH (Updated)", "email": "contact@customer-a.de", "notificationPhoneNumber": "+491701234567", "notificationEmail": "alerts@customer-a.de", "packageId": 3, "status": "active", "monthlyReportsEnabled": true, "customFields": { "internalReference": "KD-999" }, "notificationChannels": null, "notificationTargets": null, "updatedAt": "2026-02-26T19:37:00.000Z" } ``` ## Common Errors - `400` Invalid Customer identifier - `401` Unauthorized - `403` Forbidden / Organization ID not found - `404` Customer not found - `500` Failed to update customer ### Error codes and known API pitfalls URL: https://docs.uptimeify.io/api/error-codes-and-known-pitfalls Description: This page documents real integration issues that have occurred in production or testing. Summary: ## Schema | Error Code | Cause | Solution / Bug | | --- | --- | --- | | `404 Website not found` | Some website sub-endpoints previously accepted only the legacy numeric website ID, even though the docs showed `websitePublicId`. | Fixed. `GET /api/websites/:websitePublicId/check-history` and `GET /api/websites/:websitePublicId/uptime-stats` now accept public IDs and still keep legacy-ID compatibility. | | `403 Forbidden` on `GET /api/organizations/:organizationPublicId` | The route previously interpreted the path parameter directly as a number. A UUID therefore failed during permission checks. | Fixed. Organization detail and billing routes now resolve `publicId` correctly. | | `400 Bad Request` with `ZodError` on `customer-ips` or `customer-domains` | Query parameters like `organizationId=`, `page=`, or `perPage=` were sent as empty strings. Zod coerced them to `0`, which then violated min constraints. | Fixed for `organizationId`, `page`, and `perPage`. Optional still means: omit unused parameters instead of sending empty strings. | ## Monitor ownership error codes Since the [managed vs. self-service](/monitoring/managed-vs-self-service) model, monitor write endpoints of **all** types (website, DNS, ICMP, SMTP, SSH, FTP, IMAP/POP, domain, DNSBL) can return these `403` codes in `data.code`: | Code | Meaning | | --- | --- | | `managed_by_organization` | A customer-scoped caller tried to edit/delete a `managed` monitor without the `canEditManaged` exception. Open a [change request](/api/change-requests) instead. | | `selfServiceNotAllowed` | A customer-scoped caller tried to create a monitor but the customer's resolved `allowSelfService` is false. | | `selfServiceQuotaReached` | Creating (or flipping to) a `self_service` monitor would exceed the customer's `maxSelfServiceUrls` — the quota counts **all** monitor types together. | | `managementTypeOrgOnly` | A non-org-admin tried to change a monitor's `managementType`. Class flips are organization-admin-only. | | `tooManyOpenRequests` | (`429`) The customer already has 10 open change requests. | ## Incident error codes Only manual (status-page) incidents can be deleted. `DELETE /api/incidents/:id` returns this `data.code`: | Code | Meaning | | --- | --- | | `notManualIncident` | (`403`) The incident is monitor-generated. Only manual incidents created by an admin can be deleted; automatic incidents are worker-owned and are never deletable via the API. | ## Organization Reports error codes Endpoints under `/api/organization/reports` and `/api/organization/report-runs` can return these `data.code` values: | Code | Meaning | | --- | --- | | `invalidReportSchedule` | A weekly report is missing `weekday`, or a monthly report is missing `dayOfMonth` (1–28). | | `invalidReportScope` | Report scope ids are not owned by the organization, or threshold mode has no threshold set. | | `reportRunNotFound` | The requested report run does not exist for this organization. | | `reportRunNoPdf` | The report run has no archived PDF (it was an email-only report or was skipped). | ## Public IDs in DNS and DNSBL monitor routes The following path endpoints support public IDs in docs and client integrations: - `GET /api/customer-domains/:customerDomainPublicId` - `PATCH /api/customer-domains/:customerDomainPublicId` - `DELETE /api/customer-domains/:customerDomainPublicId` - `GET /api/customer-ips/:customerIpPublicId` - `PATCH /api/customer-ips/:customerIpPublicId` - `DELETE /api/customer-ips/:customerIpPublicId` Legacy numeric IDs are still accepted for backward compatibility, but public IDs are the recommended integration format. ## Update Billing Details: required body Endpoint: - `PATCH /api/organizations/:organizationPublicId/billing` Currently supported request body: ```json { "billingEmail": "billing@example.com" } ``` This endpoint currently accepts only `billingEmail`. ### Escalation Config URL: https://docs.uptimeify.io/api/escalation Description: Manage organization-level webhook escalation settings and default notification channels. Summary: The escalation config auto-creates with sensible defaults when first accessed. ## Authentication All endpoints accept either session cookies or API bearer tokens: ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Default Webhook Body Template Variables | Variable | Description | |----------|-------------| | `{{websiteName}}` | Name of the affected website | | `{{websiteUrl}}` | URL of the affected website | | `{{status}}` | Current status (e.g. `down`, `up`) | | `{{startedAt}}` | Incident start timestamp | | `{{incident}}` | Incident details object | | `{{errorMessage}}` | Error message if available | ## Endpoints - [Get Escalation Config](./get-escalation-config) - [Update Escalation Config](./update-escalation-config) - [Test Escalation Config](./test-escalation-config) ### Get Escalation Config URL: https://docs.uptimeify.io/api/escalation/get-escalation-config Description: Returns the escalation config for an organization. The :id parameter is the organization ID. If no config exists, one is auto-created with defaults. Summary: `GET /api/escalation-config/:id` Also returns the organization's default notification settings and all notification channels. ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/escalation-config/1" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "id": 1, "organizationId": 1, "webhookUrl": "https://example.com/webhook", "webhookMethod": "POST", "webhookHeaders": { "Content-Type": "application/json" }, "webhookBodyTemplate": "{\"websiteName\":\"{{websiteName}}\",...}", "webhookTimeout": 30, "webhookRetryAttempts": 3, "webhookRetryDelay": 60, "expectedStatusCodes": "200,201,202,204", "isActive": false, "lastTestedAt": null, "lastTestStatus": null, "lastTestError": null, "organization": { "defaultEmail": "ops@example.com", "defaultPhoneNumber": "+1234567890", "defaultNotificationChannels": null, "defaultNotificationTargets": null, "defaultNotificationRules": null }, "notificationChannels": [] } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` with insufficient permissions ### Test Escalation Config URL: https://docs.uptimeify.io/api/escalation/test-escalation-config Description: Tests the escalation config by sending a test webhook, PagerDuty event, or Pushover notification. All body fields are optional and override DB values for testing. Summary: `POST /api/escalation-config/:id/test` ## Request Body (all optional) | Field | Type | Description | |-------|------|-------------| | `type` | string | `pagerduty` or `pushover` for dedicated handlers | | `config` | object | PagerDuty config `{routingKey}` or Pushover config `{userKey, apiToken}` | | `webhookUrl` | string | Override webhook URL for test | | `webhookMethod` | string | Override webhook method | | `webhookHeaders` | object | Override webhook headers | | `webhookBodyTemplate` | string | Override webhook body template | | `webhookTimeout` | number | Override webhook timeout | | `expectedStatusCodes` | string | Override expected status codes | ## Example (cURL) — Webhook test ```bash curl -X POST "$BASE_URL/api/escalation-config/1/test" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "webhookUrl": "https://httpbin.org/post", "webhookMethod": "POST", "webhookTimeout": 15 }' ``` ## Example (cURL) — PagerDuty test ```bash curl -X POST "$BASE_URL/api/escalation-config/1/test" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "pagerduty", "config": { "routingKey": "your-routing-key-here" } }' ``` ## Response (webhook) ```json { "success": true, "statusCode": 200, "message": "Webhook delivered successfully" } ``` ## Response (PagerDuty) ```json { "success": true, "message": "PagerDuty event enqueued successfully" } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` with insufficient permissions ### Update Escalation Config URL: https://docs.uptimeify.io/api/escalation/update-escalation-config Description: Updates the escalation config. The :id parameter is the organization ID. If no config exists, one is upserted. Summary: `PATCH /api/escalation-config/:id` ## Request Body (all optional) | Field | Type | Description | |-------|------|-------------| | `webhookUrl` | string\|null | Webhook URL. Set to `null` to deactivate the webhook channel. | | `webhookMethod` | string | HTTP method: `POST`, `PUT`, or `PATCH` | | `webhookHeaders` | object\|string | JSON headers object | | `webhookBodyTemplate` | string | JSON body template with `{{variables}}` | | `webhookTimeout` | integer | Timeout in seconds | | `webhookRetryAttempts` | integer | Number of retries | | `webhookRetryDelay` | integer | Seconds between retries | | `expectedStatusCodes` | string | Comma-separated expected status codes | | `isActive` | boolean | Enable or disable the webhook | | `defaultEmail` | string | **Side-effect:** creates/updates an org-level email notification channel | | `defaultPhoneNumber` | string | **Side-effect:** creates/updates an org-level SMS notification channel | ## Example (cURL) ```bash curl -X PATCH "$BASE_URL/api/escalation-config/1" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "webhookUrl": "https://example.com/webhook", "webhookMethod": "POST", "webhookHeaders": { "Content-Type": "application/json" }, "webhookTimeout": 30, "webhookRetryAttempts": 3, "isActive": true, "defaultEmail": "alerts@example.com" }' ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` with insufficient permissions ## Response Returns the updated escalation config object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Examples URL: https://docs.uptimeify.io/api/examples Description: Here you’ll find step-by-step examples for common API workflows. Summary: - [Create a customer + website](/api/examples/create-customer-and-website) - [Delete a customer including all websites](/api/examples/delete-customer-and-all-websites) - [Create a customer + all monitor types](/api/examples/create-customer-and-all-monitors) - [Create a customer + multiple monitors](/api/examples/create-customer-and-multiple-monitors) ### Create a customer + all monitor types URL: https://docs.uptimeify.io/api/examples/create-customer-and-all-monitors Description: This example is useful if you want to bootstrap a customer with a complete monitoring baseline. Summary: High-level flow: 1. Create customer 2. Create website 3. Create monitors (one per monitor type) ## 1) Create customer + website Reuse: - [Create a customer + website](/api/examples/create-customer-and-website) ## 2) Create monitors (one per type) Monitor APIs are organized by type. API reference overview: - [Monitors API](/api/monitors) Typical types you might create: - DNS Monitor - ICMP Monitor - SMTP Monitor - SSH Monitor - FTP Monitor - IMAP/POP Monitor For details and required fields, follow the per-type API docs. ### Example: create a DNS monitor ```bash curl -X POST "$API_BASE_URL/api/dns-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 123, "name": "DNS: acme.example", "hostname": "acme.example", "dnsConfig": { "rrtypes": ["A", "AAAA"], "matchMode": "exact", "expectedValues": { "A": ["93.184.216.34"], "AAAA": ["2606:2800:220:1:248:1893:25c8:1946"] } } }' ``` ### Example: create an ICMP monitor ```bash curl -X POST "$API_BASE_URL/api/icmp-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 123, "name": "Ping: gateway", "hostname": "gateway.acme.example" }' ``` ## Notes - Not every installation exposes every monitor type, and required fields can vary (plan/package). - For website (HTTP) checks, start with the website’s own monitoring settings: [Website Configuration API](/api/website-configuration) ### Create a customer + multiple monitors URL: https://docs.uptimeify.io/api/examples/create-customer-and-multiple-monitors Description: This example shows how to set up multiple monitors for a single customer, e.g.: Summary: - Two different hostnames for DNS monitoring - Multiple servers for ICMP - A mix of DNS + ICMP + SMTP ## 1) Create customer + website - [Create a customer + website](/api/examples/create-customer-and-website) ## 2) Create multiple monitors ### Option A: Multiple monitors of the same type (DNS) ```bash # DNS monitor 1 curl -X POST "$API_BASE_URL/api/dns-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 123, "name": "DNS: app.acme.example", "hostname": "app.acme.example", "dnsConfig": { "rrtypes": ["A"], "matchMode": "exact", "expectedValues": { "A": ["93.184.216.34"] } } }' # DNS monitor 2 curl -X POST "$API_BASE_URL/api/dns-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 123, "name": "DNS: mail.acme.example", "hostname": "mail.acme.example", "dnsConfig": { "rrtypes": ["MX", "TXT"], "matchMode": "contains", "expectedValues": { "MX": ["10 mail.acme.example"], "TXT": ["v=spf1 include:_spf.acme.example ~all"] } } }' ``` ### Option B: Mix different monitor types ```bash # ICMP curl -X POST "$API_BASE_URL/api/icmp-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 123, "name": "Ping: edge-1", "hostname": "edge-1.acme.example" }' # SMTP curl -X POST "$API_BASE_URL/api/smtp-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 123, "name": "SMTP: outbound", "hostname": "smtp.acme.example", "port": 587 }' ``` ## Tips - Use consistent naming conventions (prefix by type: `DNS:`, `Ping:`, `SMTP:`). - Start with conservative intervals and tighten later. ## Reference - [Monitoring Types](/monitoring/monitoring-types/uptime) - [Monitors API](/api/monitors) ### Create a customer + website URL: https://docs.uptimeify.io/api/examples/create-customer-and-website Description: This example shows a typical onboarding flow: Summary: 1. Create a **customer** 2. Create a **website** for that customer 3. (Optional) Attach monitoring configuration > If you prefer the UI: you can create customers and websites in the Admin area. The API is useful for automation and bulk setups. ## Prerequisites - An API token with the required scopes - Your API base URL (e.g. `https://your-instance.tld`) See the API introduction first: - [API Introduction](/api/introduction) ## 1) Create customer API reference: - [Customers API](/api/customers) Example (pseudo request): ```bash curl -X POST "$API_BASE_URL/api/customers" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme GmbH", "email": "ops@acme.example" }' ``` Store the returned `customerId`. ## 2) Create website for the customer API reference: - [Websites API](/api/websites) ```bash curl -X POST "$API_BASE_URL/api/websites" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 123, "name": "Acme Marketing Website", "url": "https://acme.example" }' ``` Important: - `url` must include the protocol (`https://...`). ## 3) Verify the website API reference: - [Get website](/api/websites/get-website) ```bash curl -X GET "$API_BASE_URL/api/websites/456" \ -H "Authorization: Bearer $TOKEN" ``` ## Next steps - Configure monitoring behavior per website: [Website Configuration API](/api/website-configuration) - Learn which monitor types exist: [Monitoring Types](/monitoring/monitoring-types/uptime) ### Delete a customer including all websites URL: https://docs.uptimeify.io/api/examples/delete-customer-and-all-websites Description: This example focuses on a safe, explicit deletion flow. Summary: Depending on your configuration, deleting a customer may or may not automatically delete related websites. To avoid surprises, we recommend deleting websites explicitly first. ## Prerequisites - An API token with the required scopes ## 1) List websites for the customer API reference: - [List websites](/api/websites/list-websites) Pseudo request: ```bash curl -X GET "$API_BASE_URL/api/websites?customerId=123" \ -H "Authorization: Bearer $TOKEN" ``` Collect all website IDs. ## 2) Delete each website API reference: - [Delete website](/api/websites/delete-website) ```bash curl -X DELETE "$API_BASE_URL/api/websites/456" \ -H "Authorization: Bearer $TOKEN" ``` Repeat for all websites of that customer. ## 3) Delete the customer API reference: - [Customers API](/api/customers) ```bash curl -X DELETE "$API_BASE_URL/api/customers/123" \ -H "Authorization: Bearer $TOKEN" ``` ## Notes - If your backend supports cascade deletes, step 2 might be optional — but doing it explicitly keeps automation predictable. ### Introduction URL: https://docs.uptimeify.io/api/introduction Description: Welcome to the Uptimeify API documentation. With this REST API, you can programmatically manage your monitoring infrastructure – e.g., organizations, customers, websites, and alerts. Summary: ## Base URL All API requests should be sent to the following base URL: ```text https://uptimeify.io/api ``` ## Authentication The API supports **Bearer Token** authentication for integrations. ### Create API Token 1. Log in to the Uptimeify dashboard. 2. Open **Settings** > **API** in the dashboard. 3. Click on **Create Token**, enter a name, and copy the generated secret. Add the token to the `Authorization` header of your requests: ```http Authorization: Bearer wsm_ ``` Uptimeify API tokens always start with `wsm_`. If your token does not have that prefix, you are likely using the wrong credential (and requests will return `401 Unauthorized`). ### Token Scopes (Organization vs Customer) API tokens can optionally be created with a **Customer Scope**: - **Organization-wide Token**: can read/modify resources across all customers of the organization. - **Customer-Scoped Token**: can only read/modify resources (websites, maintenance windows, etc.) within that specific customer. Customer-scoped tokens are recommended for agencies and external integrations. Requests outside the scope return `403 Forbidden`. > **Note:** Session-based authentication (cookies) is used for the web interface but is not recommended for integrations. ## Response Format All responses are returned in JSON format. ### Success Response ```json { "id": 123, "name": "example-resource", "createdAt": "2023-01-01T12:00:00Z" } ``` ### Error Response Errors are returned with an appropriate HTTP status code and a JSON body containing details. ```json { "statusCode": 400, "statusMessage": "Bad Request", "message": "Validation failed: 'url' is required." } ``` ## Rate Limiting To ensure service stability, the API is rate-limited. - **Limit**: 600 requests per minute per IP - **Header**: `X-RateLimit-Remaining` shows your remaining quota - **Exceeded**: `429 Too Many Requests` ## Pages - [Generate API Token](./generate-api-token) - [Token Scopes (Organization vs Customer)](./token-scopes-organization-vs-customer) - [Success Response](./success-response) - [Error Response](./error-response) ### Error Response URL: https://docs.uptimeify.io/api/introduction/error-response Description: Errors are returned with an appropriate HTTP status code and a JSON body containing details. Summary: ```json { "statusCode": 400, "statusMessage": "Bad Request", "message": "Validation failed: 'url' is required." } ``` ## Rate limiting To ensure service stability, the API is rate-limited. - **Limit**: 600 requests per minute per IP - **Header**: `X-RateLimit-Remaining` shows your remaining quota - **Exceeded**: `429 Too Many Requests` ### Generate API Token URL: https://docs.uptimeify.io/api/introduction/generate-api-token Description: Step-by-step guide to generating an Uptimeify API token from the dashboard Settings > API page. Summary: 1. Log in to the Uptimeify dashboard. 2. Open **Settings** > **API** in the dashboard. 3. Click **Create Token**, enter a name, and copy the generated secret. Add the token to the `Authorization` header of your requests: ```http Authorization: Bearer wsm_ ``` Uptimeify API tokens always start with `wsm_`. If your token does not have that prefix, you are likely using the wrong credential. ### Success Response URL: https://docs.uptimeify.io/api/introduction/success-response Description: On success, the API returns a JSON body with the requested data. Summary: ```json { "id": 123, "name": "example-resource", "createdAt": "2023-01-01T12:00:00Z" } ``` ### Token Scopes (Organization vs Customer) URL: https://docs.uptimeify.io/api/introduction/token-scopes-organization-vs-customer Description: API tokens can optionally be created with a Customer Scope: Summary: - **Organization-wide token**: can read/modify resources across all customers of the organization. - **Customer-scoped token**: can only read/modify resources (websites, maintenance windows, etc.) within that specific customer. Customer-scoped tokens are recommended for agencies and external integrations. Requests outside the scope return `403 Forbidden`. > **Note:** Session-based authentication (cookies) is used for the web interface but is not recommended for integrations. ### Maintenance Windows URL: https://docs.uptimeify.io/api/maintenance-windows Description: Create and manage maintenance windows to suppress alerts during planned work. Windows can target a single monitor, multiple monitors, an entire customer, or any monitor carrying a given tag. Summary: Maintenance windows suppress alerts for the covered monitors during a planned time range. While a window is active the affected monitor is treated as **in maintenance** — no alerts are fired and, if the customer has a status page, the service is shown as **Maintenance** instead of **Degraded**. ## Targeting options A window can cover monitors in four ways (mutually exclusive, except that `targets` and `tagIds` may be combined): | Mode | How to specify | |------|----------------| | **Single monitor (legacy)** | One of the legacy ID fields: `websiteId`, `icmpMonitorId`, `smtpMonitorId`, `sshMonitorId`, `ftpMonitorId`, `imapPopMonitorId`, `dnsMonitorId`, `customerIpId`, `customerDomainId` | | **Multiple monitors** | `targets: [{ type, id }, ...]` array | | **By tag (dynamic)** | `tagIds: [number, ...]` — covers all monitors of the window's customer that currently carry the tag; future-tagged monitors are auto-covered | | **Customer-level** | `customerId` alone — covers every monitor belonging to that customer | ## Dynamic tag behavior Tag-based windows are evaluated live by the monitoring worker: every time a check result arrives the worker resolves which maintenance windows apply to that monitor by looking up the monitor's current tags. This means a monitor tagged *after* a window is created is automatically covered without updating the window. Removing a tag from a monitor drops it from coverage instantly. Tag windows are anchored to a single customer. You cannot create an organization-wide tag window that spans multiple customers. ## Endpoints - [List Maintenance Windows](./list) - [Create Maintenance Window](./create) - [Get Maintenance Window](./get) - [Update Maintenance Window](./update) - [Delete Maintenance Window](./delete) ### Create Maintenance Window URL: https://docs.uptimeify.io/api/maintenance-windows/create Description: Creates a new maintenance window. Accepts a single monitor (legacy), multiple monitors, tag-based (including org-wide), or customer-level targeting. Summary: `POST /api/maintenance-windows` ## Body ```json { "name": "Database migration", "startTime": "2026-07-10T22:00:00.000Z", "endTime": "2026-07-11T01:00:00.000Z", "targets": [ { "type": "website", "id": 101 }, { "type": "icmp", "id": 5 } ], "tagIds": [7], "description": "Planned schema migration", "isRecurring": false, "isActive": true } ``` ### Required fields - `name` (string): A friendly label for the window. - `startTime` (ISO 8601 datetime): When the window begins. - `endTime` (ISO 8601 datetime): When the window ends. Must be after `startTime`. - **At least one targeting field** (see below). ### Target selection (mutually exclusive modes) Exactly one targeting mode must be used. `targets` and `tagIds` may be combined within the multi-monitor mode. | Field | Type | Description | |-------|------|-------------| | `websiteId` | number | Legacy: single website monitor | | `icmpMonitorId` | number | Legacy: single ICMP monitor | | `smtpMonitorId` | number | Legacy: single SMTP monitor | | `sshMonitorId` | number | Legacy: single SSH monitor | | `ftpMonitorId` | number | Legacy: single FTP monitor | | `imapPopMonitorId` | number | Legacy: single IMAP/POP monitor | | `dnsMonitorId` | number | Legacy: single DNS monitor | | `customerIpId` | number | Legacy: single customer IP | | `customerDomainId` | number | Legacy: single customer domain | | `targets` | `{ type, id }[]` | Multi-monitor: `type` is one of `website` \| `dns` \| `icmp` \| `smtp` \| `ssh` \| `ftp` \| `imap_pop` | | `tagIds` | number[] | Tag-based: see [Tag-only (org-wide) mode](#tag-only-org-wide-mode) below | | `customerId` | number | Customer-level: covers every monitor of that customer | ### Tag-only (org-wide) mode Sending `tagIds` **without** `customerId`, `targets`, or any legacy field creates an **org-wide** maintenance window. The window dynamically covers every monitor across the entire organization that currently carries the specified tags — across all customers. ```json { "name": "Infra tag freeze", "startTime": "2026-07-10T22:00:00.000Z", "endTime": "2026-07-11T01:00:00.000Z", "tagIds": [7] } ``` - **Requires admin or editor role.** A readonly user attempting this receives `403 Forbidden`. - The tag membership is resolved live at check time — monitors tagged after the window is created are automatically covered. - All `tagIds` must belong to the same organization; mixing tags from different organizations returns `400 mixedTagOrganizations`. ### Combination rules - **Minimum one** targeting field is required. Omitting all is a Zod validation error (standard `400` with a validation body, not a `data.code` error). - **`customerId` (customer-level mode)** cannot be combined with `targets`, `tagIds`, or any legacy field. Combining them is a Zod validation error (standard `400`). - All monitors in `targets` must belong to the **same customer**; mixing customers returns `{ data: { code: "mixedCustomers" } }`. - All `tagIds` must belong to the same organization; mixing organizations returns `{ data: { code: "mixedTagOrganizations" } }`. ### Optional fields | Field | Type | Description | |-------|------|-------------| | `description` | string | Free-text notes (shown in history). | | `isRecurring` | boolean | Default `false`. Set to `true` to enable `recurrencePattern`. | | `recurrencePattern` | object | Required when `isRecurring` is `true`. See [Recurrence](#recurrence). | | `isActive` | boolean | Default `true`. Set to `false` to create a disabled window. | ### Recurrence ```json { "frequency": "weekly", "interval": 1, "daysOfWeek": [1, 3], "dayOfMonth": null, "endRecurrenceDate": "2026-12-31" } ``` | Field | Values | |-------|--------| | `frequency` | `daily` \| `weekly` \| `monthly` | | `interval` | Integer ≥ 1 (repeat every N periods) | | `daysOfWeek` | Array of `0`–`6` (0 = Sunday); used when `frequency` is `weekly` | | `dayOfMonth` | `1`–`31`; used when `frequency` is `monthly` | | `endRecurrenceDate` | ISO date string; optional, stops recurrence after this… ### Delete Maintenance Window URL: https://docs.uptimeify.io/api/maintenance-windows/delete Description: Permanently deletes a maintenance window. Active alert suppression ends immediately. Summary: `DELETE /api/maintenance-windows/{id}` ## Path Parameters - `id` (required): The numeric ID of the maintenance window to delete. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE "$BASE_URL/api/maintenance-windows/42" \ -H "Authorization: Bearer $TOKEN" ``` ## Response Returns `204 No Content` on success with an empty body. ## Common errors - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization or the window is out of scope (global supporter accounts cannot delete maintenance windows) - `404 Not Found` when no maintenance window with the given ID exists ### Get Maintenance Window URL: https://docs.uptimeify.io/api/maintenance-windows/get Description: Returns a single maintenance window by ID, including its full target and tag selection. Summary: `GET /api/maintenance-windows/{id}` ## Path Parameters - `id` (required): The numeric ID of the maintenance window. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/maintenance-windows/42" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "id": 42, "publicId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "organizationId": 10, "customerId": 1, "name": "Weekly deployment", "description": "Rolling update every Monday", "startTime": "2026-07-07T02:00:00.000Z", "endTime": "2026-07-07T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true, "targets": [ { "type": "website", "id": 101 }, { "type": "icmp", "id": 5 } ], "tags": [ { "id": 7, "name": "Production", "color": "red" } ], "websiteId": null, "icmpMonitorId": null, "smtpMonitorId": null, "sshMonitorId": null, "ftpMonitorId": null, "imapPopMonitorId": null, "dnsMonitorId": null, "customerIpId": null, "customerDomainId": null, "createdAt": "2026-06-01T09:00:00.000Z", "updatedAt": "2026-06-01T09:00:00.000Z" } ``` The `targets` array lists all explicitly selected monitors. The `tags` array lists the tags whose monitors are dynamically covered. Both may be non-empty simultaneously when the window uses a mixed multi-monitor + tag selection. ## Common errors - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization or the window belongs to an out-of-scope customer - `404 Not Found` when no maintenance window with the given ID exists ### List Maintenance Windows URL: https://docs.uptimeify.io/api/maintenance-windows/list Description: Returns all maintenance windows visible to the authenticated user, scoped by organization and optional customer filter. Summary: `GET /api/maintenance-windows` ## Query Parameters - `customerId` (optional): Filter windows by customer ID. - `organizationId` (optional): Defaults to your session organization. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/maintenance-windows?customerId=1" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": 42, "publicId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "organizationId": 10, "customerId": 1, "name": "Weekly deployment", "description": "Rolling update every Monday", "startTime": "2026-07-07T02:00:00.000Z", "endTime": "2026-07-07T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true, "targets": [ { "type": "website", "id": 101 }, { "type": "icmp", "id": 5 } ], "tags": [ { "id": 7, "name": "Production", "color": "red" } ], "websiteId": null, "icmpMonitorId": null, "smtpMonitorId": null, "sshMonitorId": null, "ftpMonitorId": null, "imapPopMonitorId": null, "dnsMonitorId": null, "customerIpId": null, "customerDomainId": null, "createdAt": "2026-06-01T09:00:00.000Z", "updatedAt": "2026-06-01T09:00:00.000Z" } ] ``` Each window includes: - `targets` — array of `{ type, id }` objects for all explicitly selected monitors (`type` is one of `website` | `dns` | `icmp` | `smtp` | `ssh` | `ftp` | `imap_pop`). - `tags` — array of tag objects `{ id, name, color }` for tag-based coverage; an empty array when the window does not use tag targeting. - Legacy single-target fields (`websiteId`, `icmpMonitorId`, etc.) remain present for backwards compatibility; they are `null` when multi-target or tag-based selection is used. ## Common errors - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Update Maintenance Window URL: https://docs.uptimeify.io/api/maintenance-windows/update Description: Partially updates a maintenance window. All fields are optional; only supplied fields are changed. When targets or tagIds are provided they replace the existing selection entirely. Summary: `PATCH /api/maintenance-windows/{id}` ## Path Parameters - `id` (required): The numeric ID of the maintenance window to update. ## Body All fields are optional. Omit a field to leave it unchanged. ```json { "name": "Extended deployment window", "endTime": "2026-07-11T03:00:00.000Z", "targets": [ { "type": "website", "id": 101 }, { "type": "dns", "id": 9 } ], "tagIds": [7, 12], "isActive": true } ``` ### Updatable fields | Field | Type | Notes | |-------|------|-------| | `name` | string | Display label | | `description` | string | Free-text notes | | `startTime` | ISO 8601 datetime | New start time | | `endTime` | ISO 8601 datetime | New end time; must be after `startTime` | | `isActive` | boolean | Enable or disable without deleting | | `isRecurring` | boolean | Toggle recurrence | | `recurrencePattern` | object | Replaces the recurrence pattern; structure identical to create | | `targets` | `{ type, id }[]` | **Replaces** the full set of explicit monitor targets | | `tagIds` | number[] | **Replaces** the full set of tag IDs | | `websiteId` / `icmpMonitorId` / … | number \| null | Legacy single-target fields | | `customerId` | number | Customer anchor (only for tag-only windows) | ### Replace semantics for targets and tagIds When `targets` or `tagIds` is included in the request body, the **entire existing selection** for that field is replaced. To remove all explicit targets send `"targets": []`; to remove all tags send `"tagIds": []`. ### Combination rules PATCH validates target and tag scope using the same resolver as create, but does **not** re-run the create-time Zod superRefine. In practice: - `customerId` cannot be combined with `targets`, `tagIds`, or legacy fields. - All monitors in `targets` must belong to the same customer; mixing returns `{ data: { code: "mixedCustomers" } }`. - An org-wide tag-only window (tags without `customerId`, `targets`, or legacy fields) can be edited by admin or editor users within the organization. ### Readonly users in scope Read-only users assigned to the window's customer may edit maintenance windows scoped to that customer. Global supporter accounts cannot. Readonly users cannot create or update org-wide tag-only windows. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/maintenance-windows/42" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"isActive": false}' ``` ## Response Returns the updated maintenance window object in the same shape as [Get Maintenance Window](./get). ## Common errors | Status | Description | |--------|-------------| | `400` (validation) | Update would leave the window with no targets, or `customerId` combined with other target fields. These are Zod validation errors; the response body is a standard validation error, **not** `{ data: { code } }`. | | `400` `{ data: { code: "mixedCustomers" } }` | `targets` contains monitors from different customers. | | `400` `{ data: { code: "mixedTagOrganizations" } }` | `tagIds` contains tags from different organizations. | | `401 Unauthorized` | Not logged in. | | `403 Forbidden` | You cannot access the window (global supporter accounts cannot edit), or you are a readonly user attempting to set an org-wide tag-only scope. | | `404 Not Found` | No maintenance window with the given ID exists. | | `404` `{ data: { code: "tagNotFound" } }` | A `tagId` does not exist in your organization. | ### Monitoring Data & Reports URL: https://docs.uptimeify.io/api/monitoring Description: API endpoints for retrieving monitoring data, check history, incident details, uptime stats, and PDF reports. Summary: ## Monitoring Data ### Get Uptime Stats `GET /api/websites/:websitePublicId/uptime-stats` Returns uptime percentages and average response times (day/month/year). ### Get Check History `GET /api/websites/:websitePublicId/check-history` Returns the latest monitoring checks for a website. ### Get Incident History `GET /api/websites/:websitePublicId/incident-history` Returns incidents for a website (latest 100). ### Get Alert History `GET /api/websites/:websitePublicId/alert-history` Returns notification/escalation attempts for incidents of a website. ### Get Monitoring Data `GET /api/websites/:websitePublicId/monitoring-data?range=day|week|month|year` Returns aggregated time series data used for charts. ### Get Incident Details `GET /api/incidents/:incidentPublicId` Returns details of a specific incident. ### List Incidents (Organization) `GET /api/incidents?organizationId=:organizationId` Lists incidents for an organization (scoped by your permissions). ## Reports ### Download PDF Report `GET /api/websites/:websitePublicId/report.pdf?period=last-week|last-month|last-quarter&startDate=YYYY-MM-DD&endDate=YYYY-MM-DD` Downloads a generated PDF report for a website. ## Endpoints - [Get Uptime Stats](./get-uptime-stats) - [Get Check History](./get-check-history) - [Get Incident History](./get-incident-history) - [Get Alert History](./get-alert-history) - [Get Monitoring Data](./get-monitoring-data) - [List Incidents (Organization)](./list-incidents) - [Get Incident Details](./get-incident-details) - [Download PDF Report](./download-report-pdf) ### Monitoring Locations URL: https://docs.uptimeify.io/api/monitoring-locations Description: Retrieve the list of countries and locations where monitoring probes are available. Summary: ## Endpoints - [List Countries](./list-countries) — authenticated, grouped by country - [List Public Locations](./list-public-locations) — public, unauthenticated ## Available Locations | Code | Name | Country | |------|------|---------| | `ch-zrh` | Zurich | Switzerland | | `cz-prg` | Prague | Czech Republic | | `de-fsn` | Falkenstein | Germany | | `de-nbg` | Nuremberg | Germany | | `fi-hel` | Helsinki | Finland | | `it-mil` | Milan | Italy | | `pl-waw` | Warsaw | Poland | ### List Countries with Locations URL: https://docs.uptimeify.io/api/monitoring-locations/list-countries Description: Returns countries that have monitoring locations with active workers. Requires authentication. Summary: `GET /api/monitoring-locations/countries` ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/monitoring-locations/countries" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "countries": [ { "code": "CH", "locations": 1, "workers": 6 }, { "code": "CZ", "locations": 1, "workers": 7 }, { "code": "DE", "locations": 2, "workers": 13 }, { "code": "FI", "locations": 1, "workers": 6 }, { "code": "IT", "locations": 1, "workers": 6 }, { "code": "PL", "locations": 1, "workers": 6 } ] } ``` ### List Public Monitoring Locations URL: https://docs.uptimeify.io/api/monitoring-locations/list-public-locations Description: Public endpoint (no authentication required) that returns all monitoring locations with active workers. Suitable for landing pages and marketing. Summary: `GET /api/public/monitoring-locations` ## Example (cURL) ```bash curl -X GET "https://uptimeify.io/api/public/monitoring-locations" \ -H "Accept: application/json" ``` ## Response ```json { "locations": [ { "id": 14, "code": "ch-zrh", "name": "Zurich (CH)", "countryCode": "CH", "activeWorkers": 6 }, { "id": 13, "code": "cz-prg", "name": "Prague (CZ)", "countryCode": "CZ", "activeWorkers": 7 }, { "id": 8, "code": "de-fsn", "name": "Falkenstein (DE)", "countryCode": "DE", "activeWorkers": 6 }, { "id": 7, "code": "de-nbg", "name": "Nuremberg (DE)", "countryCode": "DE", "activeWorkers": 7 }, { "id": 3, "code": "fi-hel", "name": "Helsinki (FI)", "countryCode": "FI", "activeWorkers": 6 }, { "id": 6, "code": "it-mil", "name": "Milan (IT)", "countryCode": "IT", "activeWorkers": 6 }, { "id": 5, "code": "pl-waw", "name": "Warsaw (PL)", "countryCode": "PL", "activeWorkers": 6 } ] } ``` `activeWorkers` is a live value and varies over time. ### Download PDF Report URL: https://docs.uptimeify.io/api/monitoring/download-report-pdf Description: Downloads a PDF report for a website. Summary: `GET /api/websites/:websitePublicId/report.pdf` ## Query Parameters You can either use a predefined `period` or a custom date range. - `period` (optional, default: `last-month`): `last-week`, `last-month`, `last-quarter` - `startDate` / `endDate` (optional): `YYYY-MM-DD` If `startDate` and `endDate` are provided, they take precedence. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -L "$BASE_URL/api/websites/6bfec6f6-245a-47ce-843b-157d97d56f88/report.pdf?period=last-month" \ -H "Authorization: Bearer $TOKEN" \ -o report.pdf ``` ## Response The response is a PDF (`application/pdf`). ## Common Errors - `400 Website public ID (UUID) required` if `:websitePublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the website - `404 Website not found` if the website does not exist ### Get Alert History URL: https://docs.uptimeify.io/api/monitoring/get-alert-history Description: Returns notification/escalation attempts (alert history) for incidents of a website. Summary: `GET /api/websites/:websitePublicId/alert-history` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites/6bfec6f6-245a-47ce-843b-157d97d56f88/alert-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "alerts": [ { "id": 987, "incidentId": 123, "type": "email", "status": "sent", "channelName": "Ops Email", "sentAt": "2026-02-26T12:11:00.000Z", "errorMessage": null } ], "total": 1 } ``` ## Common Errors - `400 Website public ID (UUID) required` if `:websitePublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the website ### Get Check History URL: https://docs.uptimeify.io/api/monitoring/get-check-history Description: Returns the latest monitoring checks for a website. Summary: `GET /api/websites/:websitePublicId/check-history` ## Query Parameters - `limit` (optional, default: `50`, max: `200`) - `checkType` (optional, supports values such as `http_status`, `ssl_check`, `combined`, `playwright`, `heartbeat`, `dns`, plus legacy values like `http` and `ssl`) ## Path Parameters - `websitePublicId` (recommended): website public UUID - Backward compatibility: legacy numeric website IDs are still accepted ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites/6bfec6f6-245a-47ce-843b-157d97d56f88/check-history?limit=25&checkType=dns" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "data": [ { "id": "chk_01H...", "status": "success", "errorMessage": null, "warningMessage": null, "timingDns": 12, "diagnostics": null, "checkedAt": "2026-02-26T12:34:56.000Z", "locationId": 7, "locationName": "Nuremberg (DE)", "locationCode": "de-nbg" } ] } ``` ## Common Errors - `400 Invalid Website identifier` if `:websitePublicId` is neither a valid UUID nor a legacy numeric ID - `400 Invalid checkType` if you send an unsupported `checkType` - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the website ### Get Incident Details URL: https://docs.uptimeify.io/api/monitoring/get-incident-details Description: Returns detailed incident data, including a timeline of failed/recovery checks and alert events. Summary: `GET /api/incidents/:incidentPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `incidentPublicId` (Path, required): Incident public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/incidents/6bfec6f6-245a-47ce-843b-157d97d56f88" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` Note: `evidenceCheck` can be `null`. `screenshotUrl` is only set when `hasScreenshot` is `true`. ## Example Response (excerpt) ```json { "incident": { "id": 123, "websiteId": 101, "type": "downtime", "status": "open", "startedAt": "2026-02-26T12:10:00.000Z", "resolvedAt": null, "statusCode": null, "errorMessage": "Timeout", "responseTimeMs": null }, "timeline": { "outageStartedAt": "2026-02-26T12:08:00.000Z", "outageStartedCheck": { "id": "chk_01H...", "checkedAt": "2026-02-26T12:08:00.000Z", "status": "failure", "statusCode": 503, "errorMessage": "Timeout", "responseTimeMs": null, "location": { "id": 7, "code": "de-nbg", "name": "Nuremberg (DE)" } }, "confirmationAt": "2026-02-26T12:10:00.000Z", "failedChecks": [], "failedChecksTotal": 2, "alertEvents": [ { "id": 987, "sentAt": "2026-02-26T12:11:00.000Z", "type": "email", "status": "sent", "channelName": "Ops Email", "errorMessage": null } ], "recoveryChecks": [], "recoveryChecksTotal": 0 }, "evidenceCheck": { "id": "chk_01H...", "checkedAt": "2026-02-26T12:08:00.000Z", "diagnostics": null, "hasScreenshot": false, "screenshotUrl": null } } ``` ## Common Errors - `400 Incident public ID (UUID) required` if `:incidentPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if the incident exists but you do not have access - `404 Incident not found` if the incident does not exist ### Get Incident History URL: https://docs.uptimeify.io/api/monitoring/get-incident-history Description: Returns incidents for a single website (latest 100), including a computed duration. Summary: `GET /api/websites/:websitePublicId/incident-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `websitePublicId` (Path, required): Website public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites/6bfec6f6-245a-47ce-843b-157d97d56f88/incident-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "incidents": [ { "id": 123, "type": "downtime", "status": "resolved", "startedAt": "Feb 26, 2026, 12:10:00", "endedAt": "Feb 26, 2026, 12:12:30", "duration": "2m 30s", "durationMs": 150000, "details": "HTTP/2 503 - Response time: 1.20s", "isOngoing": false } ], "total": 1 } ``` Note: `startedAt` and `endedAt` are formatted strings (server-side `en-US`). ## Common Errors - `400 Website public ID (UUID) required` if `:websitePublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the website - `500 Failed to fetch incident history` on unexpected errors ### Get Monitoring Data URL: https://docs.uptimeify.io/api/monitoring/get-monitoring-data Description: Returns time series data used for charts (response times, status tracker, uptime percentage). Summary: `GET /api/websites/:id/monitoring-data` To keep responses small, the endpoint down-samples the returned data points if needed. ## Query Parameters - `range` (optional, default: `day`): `day`, `week`, `month`, `year` - `maxPoints` (optional, default: `300`, max: `2000`): Limits the number of returned data points. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites/6bfec6f6-245a-47ce-843b-157d97d56f88/monitoring-data?range=week" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response (excerpt) ```json { "responseTimeData": [ { "timestamp": "2026-02-26T12:00:00.000Z", "responseTime": 123, "status": "success", "success": true, "timingDns": 12, "timingTcp": 20, "timingTls": 30, "timingTtfb": 50, "timingTransfer": 11 } ], "statusData": [ { "date": "26.02", "status": "online" } ], "uptimePercentage": "99.95", "checkSuccessRatePercentage": "99.80", "totalChecks": 100, "successfulChecks": 99 } ``` ## Common Errors - `400 Website public ID (UUID) required` if `:websitePublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the website - `500 Failed to fetch monitoring data` on server errors ### Get Uptime Stats URL: https://docs.uptimeify.io/api/monitoring/get-uptime-stats Description: Returns uptime percentages and average response times for the last day, month and year. Summary: `GET /api/websites/:websitePublicId/uptime-stats` ## Path Parameters - `websitePublicId` (recommended): website public UUID - Backward compatibility: legacy numeric website IDs are still accepted ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites/9a3d4d4d-7a4b-4f37-a9df-2a6f6d9d7a10/uptime-stats" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "day": "100.00", "month": "99.95", "year": "99.90", "dayAvgResponse": 125, "monthAvgResponse": 118, "yearAvgResponse": 120 } ``` ## Common Errors - `400 Invalid Website identifier` if `:websitePublicId` is neither a valid UUID nor a legacy numeric ID - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the website ### List Incidents (Organization) URL: https://docs.uptimeify.io/api/monitoring/list-incidents Description: Lists incidents for an organization. If organizationId is omitted, the API falls back to the organization from your session. Summary: `GET /api/incidents` Readonly users only see incidents for customers they are assigned to. ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Query Parameters - `organizationId` (optional): Organization ID. Defaults to your session organization. - `limit` (optional, default: `100`, max: `500`): Maximum number of incidents to return. - `offset` (optional, default: `0`): Pagination offset. - `includeTotal` (optional, default: `0`): If set to `1` (or `true`), the response includes `total`, `limit`, and `offset`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/incidents?organizationId=1" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` To paginate: ```bash curl -X GET "$BASE_URL/api/incidents?organizationId=1&limit=100&offset=0" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response (excerpt) ```json [ { "id": 123, "websiteId": 101, "status": "open", "severity": "downtime", "started_at": "2026-02-26T12:10:00.000Z", "resolved_at": null, "last_notified_at": "2026-02-26T12:11:00.000Z", "error_message": "Timeout", "status_code": null, "response_time_ms": null, "website": { "id": 101, "name": "Main Marketing Site", "url": "https://example.com", "status": "active" }, "customer": { "id": 12, "email": "ops@example.com", "company": "Acme Corp" } } ] ``` If `includeTotal=1`, the response shape changes to: ```json { "incidents": [], "total": 1234, "limit": 100, "offset": 0 } ``` ## Common Errors - `400 Organization ID is required` if the API cannot infer an organization - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the organization - `500 Failed to fetch incidents` on unexpected errors ### Monitors URL: https://docs.uptimeify.io/api/monitors Description: Manage protocol monitors (ICMP, SMTP, SSH, FTP, IMAP/POP). Summary: Protocol monitor detail/update/delete/check endpoints use monitor-specific `publicId` UUIDs in the path. ## Resources - [ICMP Monitors](./icmp-monitors/) - [SMTP Monitors](./smtp-monitors/) - [SSH Monitors](./ssh-monitors/) - [FTP Monitors](./ftp-monitors/) - [IMAP/POP Monitors](./imap-pop-monitors/) - [DNS Monitors](./dns-monitors/) - [DNSBL Monitoring (Customer IPs)](./dnsbl-monitoring/) - [Domain Expiry Monitoring (Customer Domains)](./domain-expiry-monitoring/) ### DNS Monitors URL: https://docs.uptimeify.io/api/monitors/dns-monitors Description: Manage DNS monitors that check DNS resolution/records for a hostname. Summary: Path-based DNS monitor endpoints use `dnsMonitorPublicId` UUIDs. ## Endpoints - [List DNS Monitors](./list-dns-monitors) - [Create DNS Monitor](./create-dns-monitor) - [Get DNS Monitor](./get-dns-monitor) - [Update DNS Monitor](./update-dns-monitor) - [Delete DNS Monitor](./delete-dns-monitor) - [Trigger DNS Check](./trigger-check-dns-monitor) - [Get DNS Monitor Check History](./get-dns-monitor-check-history) ### Create DNS Monitor URL: https://docs.uptimeify.io/api/monitors/dns-monitors/create-dns-monitor Description: Creates a new DNS monitor for a customer. Summary: `POST /api/dns-monitors` ## Request Body ```json { "customerId": "6bfec6f6-245a-47ce-843b-157d97d56f88", "name": "Example DNS", "hostname": "example.com", "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "dnsConfig": { "rrtypes": ["A", "AAAA"], "matchMode": "exact", "expectedValues": { "A": ["93.184.216.34"], "AAAA": ["2606:2800:220:1:248:1893:25c8:1946"] }, "triggerOn": { "resolveError": true, "mismatch": true } } } ``` Notes: - `customerId`, `name`, `hostname`, `dnsConfig.rrtypes`, `dnsConfig.matchMode`, and `dnsConfig.expectedValues` are required. - `customerId` accepts either the internal numeric ID or the customer `publicId` UUID. - Global supporters and readonly users cannot create DNS monitors. - `hostname` must be a hostname (no protocol, no path). - `dnsConfig.expectedValues` must contain at least one expected value for every RR type listed in `dnsConfig.rrtypes`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST \ "$BASE_URL/api/dns-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"customerId":"6bfec6f6-245a-47ce-843b-157d97d56f88","name":"Example DNS","hostname":"example.com","dnsConfig":{"rrtypes":["A"],"matchMode":"exact","expectedValues":{"A":["93.184.216.34"]},"triggerOn":{"resolveError":true,"mismatch":true}}}' ``` ## Common errors - `400 Invalid Customer identifier` - `400 hostname must be a valid hostname (no protocol, no path)` - `400 Expected values are required for RR type ` - `401 Unauthorized` - `403 Forbidden` (readonly/global supporter or no access) - `404 Customer not found` ## Response Returns the created DNS monitor object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Delete DNS Monitor URL: https://docs.uptimeify.io/api/monitors/dns-monitors/delete-dns-monitor Description: Deletes a DNS monitor. Summary: `DELETE /api/dns-monitors/:dnsMonitorPublicId` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE \ "$BASE_URL/api/dns-monitors/11111111-1111-4111-8111-111111111111" \ -H "Authorization: Bearer $TOKEN" ``` ## Common errors - `401 Unauthorized` - `403 Forbidden` - `404 DNS monitor not found` ## Response Returns `204 No Content` on success. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Get DNS Monitor URL: https://docs.uptimeify.io/api/monitors/dns-monitors/get-dns-monitor Description: Returns a single DNS monitor. Summary: `GET /api/dns-monitors/:dnsMonitorPublicId` The response contains the DNS monitor itself and does not embed the full customer record. ## Example response ```json { "id": 1, "publicId": "3c741f27-7015-4202-93ea-0f97cc6bc769", "organizationId": 2, "customerId": 2, "customerName": "Zaskoku & Haupt GbR", "name": "haupt.design", "hostname": "haupt.design", "checkInterval": 30, "timeoutSeconds": 30, "dnsConfig": { "rrtypes": ["A"], "matchMode": "exact", "triggerOn": { "mismatch": true, "resolveError": true }, "expectedValues": { "A": ["76.76.21.21"] } }, "status": "active", "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": "2026-04-03T14:55:00.005Z", "createdAt": "2026-02-23T20:24:54.731Z", "updatedAt": "2026-04-03T14:55:01.193Z" } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/dns-monitors/11111111-1111-4111-8111-111111111111" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Common errors - `400 DNS monitor public ID (UUID) required` - `401 Unauthorized` - `403 Forbidden` - `404 DNS monitor not found` ### Get DNS Monitor Alert History URL: https://docs.uptimeify.io/api/monitors/dns-monitors/get-dns-monitor-alert-history Description: Returns notification/escalation attempts (alert history) for incidents of a DNS monitor. Summary: `GET /api/dns-monitors/:dnsMonitorPublicId/alert-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `dnsMonitorPublicId` (Path, required): DNS monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/dns-monitors/11111111-1111-4111-8111-111111111111/alert-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "alerts": [ { "id": 987, "incidentId": 123, "type": "slack", "status": "sent", "channelName": "Ops Slack", "sentAt": "2026-02-26T12:11:00.000Z", "errorMessage": null } ], "total": 1 } ``` Each entry is one delivery attempt to one notification channel. `status` is `sent` or `failed` (with `errorMessage` set on failure); `type` is the channel type (e.g. `email`, `slack`, `opsgenie`). ## Common Errors - `400 DNS monitor public ID (UUID) required` if `:dnsMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### Get DNS Monitor Check History URL: https://docs.uptimeify.io/api/monitors/dns-monitors/get-dns-monitor-check-history Description: Returns recent DNS check results for a monitor. Summary: `GET /api/dns-monitors/:dnsMonitorPublicId/check-history` ## Query Parameters - `limit` (optional, default `50`, max `200`) ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/dns-monitors/11111111-1111-4111-8111-111111111111/check-history?limit=50" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "data": [] } ``` ## Common errors - `400 DNS monitor public ID (UUID) required` - `401 Unauthorized` - `403 Forbidden` ### Get DNS Monitor Incident History URL: https://docs.uptimeify.io/api/monitors/dns-monitors/get-dns-monitor-incident-history Description: Returns incidents for a single DNS monitor (latest 100), including a computed duration. Summary: `GET /api/dns-monitors/:dnsMonitorPublicId/incident-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `dnsMonitorPublicId` (Path, required): DNS monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/dns-monitors/11111111-1111-4111-8111-111111111111/incident-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "incidents": [ { "id": 123, "type": "downtime", "status": "resolved", "startedAt": "Feb 26, 2026, 12:10:00", "endedAt": "Feb 26, 2026, 12:12:30", "duration": "2m 30s" } ], "total": 1 } ``` `type` reflects the failure category for this monitor; `status` is `active` (ongoing) or `resolved`. Ongoing incidents have a `null` `endedAt`. ## Common Errors - `400 DNS monitor public ID (UUID) required` if `:dnsMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### List DNS Monitors URL: https://docs.uptimeify.io/api/monitors/dns-monitors/list-dns-monitors Description: Lists DNS monitors for an organization (with pagination). Summary: `GET /api/dns-monitors` Each item contains the DNS monitor itself and does not embed the full customer record. ## Query Parameters - `organizationId` (optional): defaults to your session organization - `customerId` (optional) - `search` (optional) - `page` (optional, default `1`) - `perPage` (optional, default `50`, max `200`) ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/dns-monitors?organizationId=1&page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "items": [ { "id": 5, "publicId": "79fbe9b0-f9c6-4026-86de-1dbebc84d9bb", "organizationId": 2, "customerId": 2, "customerName": "Zaskoku & Haupt GbR", "name": "Primary DNS Monitor", "hostname": "claas.sh", "checkInterval": 30, "timeoutSeconds": 30, "dnsConfig": {}, "allowedCheckCountryCodes": null, "status": "active", "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": "2026-04-03T14:54:56.561Z", "createdAt": "2026-04-03T14:54:56.383Z", "updatedAt": "2026-04-03T14:54:56.740Z" } ], "total": 0, "page": 1, "perPage": 50 } ``` ## Common errors - `400 Invalid organizationId` when `organizationId` is invalid - `400 Invalid customerId` when `customerId` is invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Trigger DNS Check URL: https://docs.uptimeify.io/api/monitors/dns-monitors/trigger-check-dns-monitor Description: Triggers an immediate DNS check across eligible monitoring locations. Summary: `POST /api/dns-monitors/:dnsMonitorPublicId/trigger-check` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST \ "$BASE_URL/api/dns-monitors/11111111-1111-4111-8111-111111111111/trigger-check" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "success": true, "message": "Checks triggered successfully", "dnsMonitorId": 123, "locationCodes": ["de-nbg"], "queueNames": ["dns-monitor-checks-de-nbg"] } ``` ## Common errors - `400 DNS monitor public ID (UUID) required` - `401 Unauthorized` - `403 Forbidden` (requires write access) - `503 No active monitoring locations available` ### Update DNS Monitor URL: https://docs.uptimeify.io/api/monitors/dns-monitors/update-dns-monitor Description: Updates a DNS monitor. Summary: `PATCH /api/dns-monitors/:dnsMonitorPublicId` Notes: - Readonly users may only change `status`. - Global supporters cannot update DNS monitors. - If you send `customerId`, it accepts either the internal numeric ID or the customer `publicId` UUID. ## Request Body (example) ```json { "customerId": "6764e84f-f02a-43e6-a46d-cecaec556723", "status": "maintenance", "name": "Primary DNS Monitor", "hostname": "claas.sh", "checkInterval": 30, "timeoutSeconds": 30, "dnsConfig": { "rrtypes": ["A"], "matchMode": "exact", "expectedValues": { "A": ["76.76.21.21"] }, "triggerOn": { "resolveError": true, "mismatch": true } } } ``` If you send `dnsConfig`, it must include `rrtypes`, `matchMode`, and at least one `expectedValues` entry for every RR type listed. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH \ "$BASE_URL/api/dns-monitors/11111111-1111-4111-8111-111111111111" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"customerId":"6764e84f-f02a-43e6-a46d-cecaec556723","status":"maintenance","name":"Primary DNS Monitor","hostname":"claas.sh","checkInterval":30,"timeoutSeconds":30,"dnsConfig":{"rrtypes":["A"],"matchMode":"exact","expectedValues":{"A":["76.76.21.21"]},"triggerOn":{"resolveError":true,"mismatch":true}}}' ``` ## Common errors - `400 DNS monitor ID is required` - `400 Invalid status` - `400 Invalid Customer identifier` - `400 Expected values are required for RR type ` - `401 Unauthorized` - `403 Forbidden` - `404 Customer not found` ## Response Returns the updated DNS monitor object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### DNSBL Monitoring (Customer IPs) URL: https://docs.uptimeify.io/api/monitors/dnsbl-monitoring Description: DNSBL monitoring is configured via customer IPs. These IPs are periodically checked against DNS-based blacklists. Summary: ## Endpoints - [List Customer IPs (Org)](./list-customer-ips) - [Get Customer IP](./get-customer-ip) - [Update Customer IP](./update-customer-ip) - [Delete Customer IP](./delete-customer-ip) - [List Customer IPs (Customer)](./list-customer-ips-for-customer) - [Create Customer IP (Customer)](./create-customer-ip-for-customer) ### Create Customer Ip For Customer URL: https://docs.uptimeify.io/api/monitors/dnsbl-monitoring/create-customer-ip-for-customer Summary: title: Create Customer IP (Customer) description: POST /api/customers/:customerPublicId/ips --- # Create Customer IP (Customer) `POST /api/customers/:customerPublicId/ips` Creates a new customer IP for DNSBL monitoring. ## Request Body ```json { "ipAddress": "203.0.113.10", "label": "Mail Server", "ipFamily": "v4", "status": "active" } ``` Notes: - `customerPublicId` should be the customer public UUID. Legacy numeric customer IDs remain supported for compatibility. - `ipFamily` is optional; if omitted, it is inferred from the IP address. - If `ipFamily` is provided, it must match the IP address version. - Creating an `active` IP may be blocked by quota limits. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST "$BASE_URL/api/customers/6bfec6f6-245a-47ce-843b-157d97d56f88/ips" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"ipAddress":"203.0.113.10","label":"Mail Server","status":"active"}' ``` ## Response Returns the newly created customer IP record. ## Common errors - `400 Invalid Customer identifier` when `:customerPublicId` is missing/invalid - `400 Invalid IP address` when `ipAddress` is invalid - `400 IP family mismatch...` when `ipFamily` does not match the IP - `401 Unauthorized` when you are not logged in - `403 Forbidden` for readonly/global supporter users, or when you cannot access the customer - `403 Active IP limit reached...` when creating/activating would exceed your quota - `404 Customer not found` when the customer does not exist - `409 IP already exists for this customer` when the IP is already present ### Delete Customer IP URL: https://docs.uptimeify.io/api/monitors/dnsbl-monitoring/delete-customer-ip Description: Deletes a customer IP. Summary: `DELETE /api/customer-ips/:customerIpPublicId` Notes: - Readonly users and global supporters cannot delete customer IPs. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE "$BASE_URL/api/customer-ips/11111111-1111-4111-8111-111111111111" \ -H "Authorization: Bearer $TOKEN" ``` ## Example Response ```json { "success": true } ``` ## Common errors - `400 Invalid IP identifier` when `:customerIpPublicId` is neither a valid UUID nor a legacy numeric ID - `401 Unauthorized` when you are not logged in - `403 Forbidden` for readonly/global supporter users, or when you cannot access the customer - `404 IP not found` when the IP does not exist ### Get Customer IP URL: https://docs.uptimeify.io/api/monitors/dnsbl-monitoring/get-customer-ip Description: Returns a customer IP including DNSBL status (if available). Summary: `GET /api/customer-ips/:customerIpPublicId` The response contains the customer IP itself and, if available, a `dnsbl` object. It does not embed the full customer record. ## Path Parameters - `customerIpPublicId` (recommended): customer IP public UUID - Backward compatibility: legacy numeric IDs are still accepted ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/customer-ips/11111111-1111-4111-8111-111111111111" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example response ```json { "id": 1, "publicId": "a19effb9-eb5f-459b-b5d6-2f615b574651", "customerId": 2, "customerName": "Zaskoku & Haupt GbR", "label": "Kurbelix Adminserver", "ipAddress": "77.75.254.185", "ipFamily": "v4", "status": "active", "createdAt": "2026-02-03T15:06:46.469Z", "updatedAt": "2026-02-03T15:06:46.469Z", "dnsbl": { "isListed": true, "listedCount": 1, "listings": [ { "name": "all.s5h.net", "reason": "Listed in all.s5h.net", "listKey": "all.s5h.net", "delistUrl": "http://s5h.net", "resultCode": "127.0.0.2" } ], "lastError": null, "lastCheckedAt": "2026-04-03T15:13:00.083Z", "lastChangedAt": "2026-02-04T10:00:00.121Z", "lastListedAt": "2026-04-03T15:13:00.083Z", "lastCleanAt": null, "lastNotifiedListedAt": "2026-04-02T20:55:04.969Z", "lastNotifiedCleanAt": null } } ``` ## Common errors - `400 Invalid IP identifier` when `:customerIpPublicId` is neither a valid UUID nor a legacy numeric ID - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the customer - `404 IP not found` when the IP does not exist ### List Customer IPs (Org) URL: https://docs.uptimeify.io/api/monitors/dnsbl-monitoring/list-customer-ips Description: Lists customer IPs within an organization (pagination + search). This is the primary API for DNSBL monitoring configuration. Summary: `GET /api/customer-ips` ## Query Parameters - `organizationId` (optional): defaults to your session organization - `customerId` (optional): accepts the customer public UUID (recommended) or a legacy numeric customer ID - `search` (optional) - `page` (optional, default `1`) - `perPage` (optional, default `50`, max `200`) ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/customer-ips?organizationId=1&page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "items": [], "total": 0, "page": 1, "perPage": 50 } ``` ## Common errors - `400 Organization ID required` when the organization cannot be derived - `400` query validation errors (e.g. invalid `organizationId`, `customerId`, `page`, `perPage`) - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### List Customer Ips For Customer URL: https://docs.uptimeify.io/api/monitors/dnsbl-monitoring/list-customer-ips-for-customer Summary: title: List Customer IPs (Customer) description: GET /api/customers/:customerPublicId/ips --- # List Customer IPs (Customer) `GET /api/customers/:customerPublicId/ips` Lists IPs for a single customer, including DNSBL status. ## Path Parameters - `customerPublicId` (recommended): Customer public UUID - Legacy compatibility: numeric customer IDs are still accepted ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/customers/6bfec6f6-245a-47ce-843b-157d97d56f88/ips" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response Returns an array of customer IP objects. Each item may include a `dnsbl` object. ## Common errors - `400 Invalid Customer identifier` when `:customerPublicId` is missing/invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the customer - `404 Customer not found` when the customer does not exist ### Update Customer IP URL: https://docs.uptimeify.io/api/monitors/dnsbl-monitoring/update-customer-ip Description: Updates a customer IP (e.g. label or status). Summary: `PATCH /api/customer-ips/:customerIpPublicId` Notes: - Readonly users and global supporters cannot update customer IPs. - Activating an IP can be denied when quota limits are reached. ## Request Body ```json { "label": "Mail Server", "status": "active" } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/customer-ips/11111111-1111-4111-8111-111111111111" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"label":"Mail Server","status":"active"}' ``` ## Response Returns the updated customer IP record. ## Common errors - `400 Invalid IP identifier` when `:customerIpPublicId` is neither a valid UUID nor a legacy numeric ID - `400` body validation errors (e.g. invalid `status`) - `401 Unauthorized` when you are not logged in - `403 Forbidden` for readonly/global supporter users, or when you cannot access the customer - `403 Active IP limit reached...` when activating would exceed your quota - `404 IP not found` when the IP does not exist ### Domain Expiry Monitoring (Customer Domains) URL: https://docs.uptimeify.io/api/monitors/domain-expiry-monitoring Description: Domain expiry monitoring is configured via customer domains. Summary: ## Endpoints - [Create Customer Domain (Customer)](./create-customer-domain) - [List Customer Domains (Org)](./list-customer-domains) - [Get Customer Domain](./get-customer-domain) - [Update Customer Domain](./update-customer-domain) - [Delete Customer Domain](./delete-customer-domain) - [List Domain Expiry (Websites)](./list-domain-expiry-websites) ### Create Customer Domain URL: https://docs.uptimeify.io/api/monitors/domain-expiry-monitoring/create-customer-domain Summary: title: Create Customer Domain (Customer) description: POST /api/customers/:customerPublicId/domains --- # Create Customer Domain (Customer) `POST /api/customers/:customerPublicId/domains` Creates a customer domain for expiry monitoring. ## Request Body ```json { "domainName": "example.com", "label": "Main Domain", "status": "active", "expiryWarningDays": 30, "expiryErrorDays": 7 } ``` Notes: - `customerPublicId` should be the customer public UUID. Legacy numeric customer IDs remain supported for compatibility. - `domainName` must be a valid domain like `example.com` (no protocol, no path). - Creating an `active` domain may be blocked by quota limits. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST "$BASE_URL/api/customers/6bfec6f6-245a-47ce-843b-157d97d56f88/domains" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"domainName":"example.com","label":"Main Domain","status":"active","expiryWarningDays":30,"expiryErrorDays":7}' ``` ## Response Returns the newly created customer domain record. ## Common errors - `400 Invalid Customer identifier` when `:customerPublicId` is missing/invalid - `400 Invalid domain name...` when `domainName` is invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` for readonly/global supporter users, or when you cannot access the customer - `403 Active domain limit reached...` when creating/activating would exceed your quota - `404 Customer not found` when the customer does not exist ### Delete Customer Domain URL: https://docs.uptimeify.io/api/monitors/domain-expiry-monitoring/delete-customer-domain Description: Deletes a customer domain. Summary: `DELETE /api/customer-domains/:customerDomainPublicId` Notes: - Readonly users and global supporters cannot delete customer domains. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE "$BASE_URL/api/customer-domains/22222222-2222-4222-8222-222222222222" \ -H "Authorization: Bearer $TOKEN" ``` ## Example Response ```json { "success": true } ``` ## Common errors - `400 Invalid Domain identifier` when `:customerDomainPublicId` is neither a valid UUID nor a legacy numeric ID - `401 Unauthorized` when you are not logged in - `403 Forbidden` for readonly/global supporter users, or when you cannot access the domain/customer - `404 Domain not found` when the domain does not exist ### Get Customer Domain URL: https://docs.uptimeify.io/api/monitors/domain-expiry-monitoring/get-customer-domain Description: Returns a single customer domain. Summary: `GET /api/customer-domains/:customerDomainPublicId` The response contains the customer domain itself and does not embed the full customer record. ## Path Parameters - `customerDomainPublicId` (recommended): customer domain public UUID - Backward compatibility: legacy numeric IDs are still accepted Notes: - Some registries/TLDs (e.g. `.de`) may not publish an expiration date via RDAP. In that case, `expiry.domainExpiresAt` can be `null` and `expiry.lastError` may contain an explanatory message. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/customer-domains/22222222-2222-4222-8222-222222222222" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example response ```json { "id": 20, "publicId": "d70884d9-4cef-4fe5-9b15-341b7dd9e196", "customerId": 2, "customerName": "Zaskoku & Haupt GbR", "label": "Primary Domain", "domainName": "cacheassist.io", "status": "active", "expiryWarningDays": 30, "expiryErrorDays": 7, "createdAt": "2026-04-03T15:28:40.602Z", "updatedAt": "2026-04-03T15:28:40.602Z", "expiry": { "domainExpiresAt": null, "domainRegistrar": null, "isExpired": false, "lastError": "RDAP query error for cacheassist.io: fetch failed", "lastCheckedAt": "2026-04-03T15:29:00.200Z", "lastChangedAt": null, "lastNotifiedWarningAt": null, "lastNotifiedErrorAt": null, "lastNotifiedExpiredAt": null } } ``` ## Common errors - `400 Invalid Domain identifier` when `:customerDomainPublicId` is neither a valid UUID nor a legacy numeric ID - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the domain/customer - `404 Domain not found` when the domain does not exist ### List Customer Domains (Org) URL: https://docs.uptimeify.io/api/monitors/domain-expiry-monitoring/list-customer-domains Description: Lists customer domains within an organization (pagination + search). Summary: `GET /api/customer-domains` ## Query Parameters - `organizationId` (optional): defaults to your session organization - `customerId` (optional): accepts the customer public UUID (recommended) or a legacy numeric customer ID - `search` (optional) - `page` (optional, default `1`) - `perPage` (optional, default `50`, max `200`) ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/customer-domains?organizationId=1&page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response Returns a paginated response: ```json { "items": [ { "id": 1, "publicId": "34eb0ec1-315d-45c4-aefe-0e5d12b11183", "customerId": 2, "customerName": "Zaskoku & Haupt GbR", "customerPublicId": "6764e84f-f02a-43e6-a46d-cecaec556723", "label": null, "domainName": "digitalduett.com", "status": "active", "expiryWarningDays": 30, "expiryErrorDays": 7, "createdAt": "2026-02-13T21:21:03.001Z", "updatedAt": "2026-02-13T21:21:03.001Z", "expiry": { "domainExpiresAt": "2026-12-20T20:44:45.000Z", "domainRegistrar": "NameCheap, Inc.", "isExpired": false, "lastError": null, "lastCheckedAt": "2026-04-03T10:59:00.321Z", "lastChangedAt": "2026-04-03T10:59:00.321Z", "lastNotifiedWarningAt": null, "lastNotifiedErrorAt": null, "lastNotifiedExpiredAt": null } } ], "total": 0, "page": 1, "perPage": 50 } ``` Each item includes flat customer fields plus an `expiry` object (or `null`). ## Common errors - `400 Organization ID required` when the organization cannot be derived - `400` query validation errors (e.g. invalid `organizationId`, `customerId`, `page`, `perPage`) - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### List Domain Expiry (Websites) URL: https://docs.uptimeify.io/api/monitors/domain-expiry-monitoring/list-domain-expiry-websites Description: Lists websites with latest known domain expiry information. Summary: `GET /api/domains` ## Query Parameters - `organizationId` (optional): defaults to your session organization - `customerId` (optional) - `search` (optional) - `page` (optional, default `1`) - `perPage` (optional, default `50`, max `200`) ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/domains?organizationId=1&page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "items": [ { "id": 101, "name": "Example Website", "url": "https://example.com", "status": "active", "customerId": 10, "customerName": "Example Customer", "checkDomainExpiryEnabled": true, "domainExpiryNoticeDays": 30, "domainExpiryErrorDays": 7, "domainExpiresAt": "2026-12-31T00:00:00.000Z", "domainRegistrar": "Example Registrar", "lastDomainCheckAt": "2026-03-03T10:00:00.000Z", "daysUntilExpiry": 303, "expiryStatus": "ok" } ], "total": 1, "page": 1, "perPage": 50 } ``` ## Field notes - `expiryStatus` can be: `ok`, `warning`, `critical`, `expired`, `unknown`, `disabled`. - `daysUntilExpiry` is `null` when no expiration date is available. ## Common errors - `400 Organization ID required` when the organization cannot be derived - `400 Invalid customerId` when `customerId` is invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Update Customer Domain URL: https://docs.uptimeify.io/api/monitors/domain-expiry-monitoring/update-customer-domain Description: Updates a customer domain (e.g. label, status, expiry thresholds). Summary: `PATCH /api/customer-domains/:customerDomainPublicId` Notes: - Readonly users and global supporters cannot update customer domains. - Activating a disabled domain can be denied when quota limits are reached. ## Request Body ```json { "label": "Main Domain", "status": "active", "expiryWarningDays": 30, "expiryErrorDays": 7 } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/customer-domains/22222222-2222-4222-8222-222222222222" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"status":"active"}' ``` ## Response Returns the updated customer domain record. ## Common errors - `400` body validation errors (e.g. invalid thresholds) - `400 Invalid Domain identifier` when `:customerDomainPublicId` is neither a valid UUID nor a legacy numeric ID - `401 Unauthorized` when you are not logged in - `403 Forbidden` for readonly/global supporter users, or when you cannot access the domain/customer - `403 Active domain limit reached...` when activating would exceed your quota - `404 Domain not found` when the domain does not exist ### FTP Monitors URL: https://docs.uptimeify.io/api/monitors/ftp-monitors Description: Manage FTP monitors. Summary: Path-based FTP monitor endpoints use `ftpMonitorPublicId` UUIDs. ## Endpoints - [List FTP Monitors](./list-ftp-monitors) - [Create FTP Monitor](./create-ftp-monitor) - [Get FTP Monitor](./get-ftp-monitor) - [Get FTP Monitor Details](./get-ftp-monitor-details) - [Get FTP Monitor Check History](./get-ftp-monitor-check-history) - [Update FTP Monitor (Change Status)](./update-ftp-monitor) - [Delete FTP Monitor](./delete-ftp-monitor) - [Trigger FTP Check](./trigger-check-ftp-monitor) ### Create FTP Monitor URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/create-ftp-monitor Description: Creates a new FTP monitor. Summary: `POST /api/ftp-monitors` ## Authentication This endpoint requires an API token: `Authorization: Bearer ` ## Request Body - `customerId` (required, number | string): internal numeric customer ID or customer `publicId` UUID - `name` (required, string) - `hostname` (required, string): Must be a hostname (no protocol, no path). - `port` (optional, number | null): If omitted/null, the worker uses a default port. - `status` (optional): `active`, `maintenance`, `disabled` (also accepts `inactive` and normalizes it to `disabled`) - `checkInterval` (optional, number): Minutes (min: 1, max: 60) - `timeoutSeconds` (optional, number): Seconds (min: 1, max: 60) - `ftpConfig` (optional, object): FTP connection options (stored as JSON) ### `ftpConfig` The monitoring worker reads these keys: - `user` (optional, string): Defaults to `anonymous` - `password` (optional, string): Defaults to `anonymous@` - `secure` (optional, boolean | `"implicit"`): - `false` (default): plain FTP - `true`: explicit TLS - `"implicit"`: implicit TLS (worker defaults port to `990` when `port` is not provided) ```json { "customerId": "6764e84f-f02a-43e6-a46d-cecaec556723", "name": "FTP Availability", "hostname": "claas.sh", "port": 21, "status": "active", "checkInterval": 5, "timeoutSeconds": 30, "ftpConfig": { "user": "root", "password": "exampleRoot", "secure": "explicit" } } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST \ "$BASE_URL/api/ftp-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"customerId":"6764e84f-f02a-43e6-a46d-cecaec556723","name":"FTP Availability","hostname":"claas.sh","port":21,"status":"active","checkInterval":5,"timeoutSeconds":30,"ftpConfig":{"user":"root","password":"exampleRoot","secure":"explicit"}}' ``` ## Response ```json { "id": 400, "organizationId": 1, "customerId": 2, "name": "FTP Availability", "hostname": "claas.sh", "port": 21, "status": "active", "checkInterval": 5, "timeoutSeconds": 30, "allowedCheckCountryCodes": null, "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-25T10:00:00.000Z", "updatedAt": "2026-02-25T10:00:00.000Z", "config": { "user": "root", "password": "exampleRoot", "secure": "explicit" }, "ftpConfig": { "user": "root", "password": "exampleRoot", "secure": "explicit" } } ``` ## Common Errors - `400 Invalid Customer identifier` if `customerId` is neither a valid UUID nor a legacy numeric ID - `400 hostname must be a valid hostname (no protocol, no path)` on invalid hostnames - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access or are not allowed to create monitors (e.g. read-only or global supporter) - `404 Customer not found` if the `customerId` does not exist ### Delete FTP Monitor URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/delete-ftp-monitor Description: Deletes an FTP monitor. Summary: `DELETE /api/ftp-monitors/:ftpMonitorPublicId` ## Authentication `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE \ "$BASE_URL/api/ftp-monitors/55555555-5555-4555-8555-555555555555" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true } ``` ## Common Errors - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have write access (e.g. global supporter or read-only) - `404 FTP monitor not found` if the monitor does not exist ### Get FTP Monitor URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/get-ftp-monitor Description: Returns details of a specific FTP monitor. Summary: `GET /api/ftp-monitors/:ftpMonitorPublicId` The response contains the FTP monitor itself and does not embed the full customer record. ## Authentication `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/ftp-monitors/55555555-5555-4555-8555-555555555555" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "id": 400, "organizationId": 1, "customerId": 10, "name": "Partner FTP", "hostname": "ftp.example.com", "port": 21, "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "allowedCheckCountryCodes": null, "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-25T10:00:00.000Z", "updatedAt": "2026-02-25T10:00:00.000Z", "config": { "user": "monitor", "password": "", "secure": false }, "ftpConfig": { "user": "monitor", "password": "", "secure": false } } ``` ## Common Errors - `400 FTP monitor public ID (UUID) required` if `ftpMonitorPublicId` is missing or invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access - `404 FTP monitor not found` if the monitor does not exist ### Get FTP Monitor Alert History URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/get-ftp-monitor-alert-history Description: Returns notification/escalation attempts (alert history) for incidents of a FTP monitor. Summary: `GET /api/ftp-monitors/:ftpMonitorPublicId/alert-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/ftp-monitors/11111111-1111-4111-8111-111111111111/alert-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "alerts": [ { "id": 987, "incidentId": 123, "type": "slack", "status": "sent", "channelName": "Ops Slack", "sentAt": "2026-02-26T12:11:00.000Z", "errorMessage": null } ], "total": 1 } ``` Each entry is one delivery attempt to one notification channel. `status` is `sent` or `failed` (with `errorMessage` set on failure); `type` is the channel type (e.g. `email`, `slack`, `opsgenie`). ## Common Errors - `400 FTP monitor public ID (UUID) required` if `:ftpMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### Get FTP Monitor Check History URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/get-ftp-monitor-check-history Description: Returns recent FTP check results for a monitor. Summary: `GET /api/ftp-monitors/:ftpMonitorPublicId/check-history` ## Authentication `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. - `limit` (Query, optional): Number of results (default: 50, max: 200) ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/ftp-monitors/55555555-5555-4555-8555-555555555555/check-history?limit=25" \ -H "Authorization: Bearer $TOKEN" ``` ## Example Response ```json { "data": [ { "id": "2fd6d5ab-1e2a-4b4f-9c42-0f3a33a4a1d2", "status": "success", "errorMessage": null, "warningMessage": null, "timingFtp": 123, "diagnostics": { "message": "FTP connection successful" }, "checkedAt": "2026-02-25T10:05:00.000Z", "locationId": 7, "locationName": "Nuremberg (DE)", "locationCode": "de-nbg" } ] } ``` ## Common Errors - `400 FTP monitor public ID (UUID) required` if `ftpMonitorPublicId` is missing or invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access - `404 FTP monitor not found` if the monitor does not exist ### Get FTP Monitor Details URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/get-ftp-monitor-details Description: Returns the FTP monitor detail page data in one call (mega endpoint). Summary: `GET /api/ftp-monitors/:ftpMonitorPublicId/details` ## Authentication `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. ## Query Parameters - `range` (optional): `day` (default), `week`, `month`, `year` - `date` (optional): Reference date (ISO string) - `startDate` / `endDate` (optional): Override the time window (ISO strings) - `granularity` (optional): When omitted the server may aggregate automatically for large time ranges. Use `granularity=raw` to force raw data. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/ftp-monitors/55555555-5555-4555-8555-555555555555/details?range=day" \ -H "Authorization: Bearer $TOKEN" ``` ## Example Response (shape) The response is a single object with these top-level keys: ```json { "ftpMonitorId": 400, "monitor": {}, "latestCheck": {}, "uptimeStats": { "day": "100.00", "month": "100.00", "year": "100.00", "dayAvgResponse": 120, "monthAvgResponse": 130, "yearAvgResponse": 140 }, "uptimeStatsMeta": {}, "monitoringData": { "responseTimeData": [], "statusData": [], "uptimePercentage": "100.00", "checkSuccessRatePercentage": "100.00", "totalChecks": 10, "successfulChecks": 10 }, "incidents": { "history": [], "total": 0, "ongoing": 0, "totalDowntime": "0s" }, "alerts": { "history": [], "total": 0, "notificationContext": {} }, "testResultLog": null, "maintenance": { "inMaintenance": false, "activeWindows": [], "allWindows": [] } } ``` ## Common Errors - `400 Invalid FTP monitor public ID (UUID)` if `ftpMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access - `500 Failed to fetch FTP monitor details` on server errors ### Get FTP Monitor Incident History URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/get-ftp-monitor-incident-history Description: Returns incidents for a single FTP monitor (latest 100), including a computed duration. Summary: `GET /api/ftp-monitors/:ftpMonitorPublicId/incident-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/ftp-monitors/11111111-1111-4111-8111-111111111111/incident-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "incidents": [ { "id": 123, "type": "downtime", "status": "resolved", "startedAt": "Feb 26, 2026, 12:10:00", "endedAt": "Feb 26, 2026, 12:12:30", "duration": "2m 30s" } ], "total": 1 } ``` `type` reflects the failure category for this monitor; `status` is `active` (ongoing) or `resolved`. Ongoing incidents have a `null` `endedAt`. ## Common Errors - `400 FTP monitor public ID (UUID) required` if `:ftpMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### List FTP Monitors URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/list-ftp-monitors Description: Lists FTP monitors in an organization. Summary: `GET /api/ftp-monitors` ## Authentication `Authorization: Bearer ` ## Parameters - `organizationId` (Query, optional): Organization ID. Defaults to the current user's organization. - `customerId` (Query, optional): Filter by customer ID. - `search` (Query, optional): Search by monitor name, hostname, or customer. - `page` (Query, optional): Page number (default: 1). - `perPage` (Query, optional): Items per page (default: 50, max: 200). Note: The results are also limited by your customer scope (if your account is restricted to a subset of customers). ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/ftp-monitors?page=1&perPage=50&search=ftp" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "items": [ { "id": 400, "organizationId": 1, "customerId": 10, "customerName": "Example Customer", "name": "Partner FTP", "hostname": "ftp.example.com", "port": 21, "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "allowedCheckCountryCodes": null, "config": { "user": "monitor", "password": "", "secure": false }, "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-25T10:00:00.000Z", "updatedAt": "2026-02-25T10:00:00.000Z" } ], "total": 1, "page": 1, "perPage": 50 } ``` Each item contains the FTP monitor itself and a flat `customerName`, not a full embedded customer record. ## Common Errors - `400 Invalid organizationId` if `organizationId` is not a valid number - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the organization ### Trigger FTP Check URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/trigger-check-ftp-monitor Description: Triggers an immediate check from all eligible monitoring locations. Summary: `POST /api/ftp-monitors/:ftpMonitorPublicId/trigger-check` ## Authentication `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST \ "$BASE_URL/api/ftp-monitors/55555555-5555-4555-8555-555555555555/trigger-check" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true, "message": "Checks triggered successfully", "ftpMonitorId": 400, "locationCodes": ["DE", "CH"], "queueNames": ["ftp-monitor-checks-DE", "ftp-monitor-checks-US"] } ``` ## Common Errors - `400 FTP monitor public ID (UUID) required` if `ftpMonitorPublicId` is missing or invalid - `400 No eligible monitoring locations for the selected allowed countries` if your country restrictions match no active locations - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have write access - `503 No active monitoring locations available` if no worker locations are active ### Update FTP Monitor (Change Status) URL: https://docs.uptimeify.io/api/monitors/ftp-monitors/update-ftp-monitor Description: Updates an FTP monitor and/or changes its status. Summary: `PATCH /api/ftp-monitors/:ftpMonitorPublicId` ## Authentication `Authorization: Bearer ` ## Parameters - `ftpMonitorPublicId` (Path, required): FTP monitor public UUID. ## Request Body - `status` (optional): `active`, `maintenance`, `disabled` (also accepts `inactive`/`paused` and normalizes them to `disabled`) - `customerId` (optional, number): Must belong to the same organization - `name` (optional, string) - `hostname` (optional, string): Must be a hostname (no protocol, no path) - `port` (optional, number | null) - `checkInterval` (optional, number) - `timeoutSeconds` (optional, number) - `allowedCheckCountryCodes` (optional, string[] | null): ISO-3166-1 alpha-2, e.g. `"DE"`, `"CH"` - `ftpConfig` (optional, object): Replaces the stored FTP config JSON - `config` (optional, object): Alias of `ftpConfig` Note: Read-only users may only change `status`. Note: If you omit `ftpConfig`/`config`, the current config remains unchanged. ```json { "status": "maintenance" } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH \ "$BASE_URL/api/ftp-monitors/55555555-5555-4555-8555-555555555555" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"status":"active","allowedCheckCountryCodes":["DE","CH"],"ftpConfig":{"user":"monitor","password":"","secure":false}}' ``` ## Response ```json { "id": 400, "status": "maintenance", "config": {}, "ftpConfig": {} } ``` ## Common Errors - `400 Invalid status` if `status` is not valid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have write access (e.g. read-only user tries to change other fields, or global supporter) - `404 FTP monitor not found` if the monitor does not exist ### ICMP Monitors URL: https://docs.uptimeify.io/api/monitors/icmp-monitors Description: Manage ICMP (ping) monitors. Summary: Path-based ICMP monitor endpoints use `icmpMonitorPublicId` UUIDs. ## Endpoints - [List ICMP Monitors](./list-icmp-monitors) - [Create ICMP Monitor](./create-icmp-monitor) - [Get ICMP Monitor](./get-icmp-monitor) - [Get ICMP Monitor Details](./get-icmp-monitor-details) - [Get ICMP Monitor Check History](./get-icmp-monitor-check-history) - [Update ICMP Monitor](./update-icmp-monitor) - [Delete ICMP Monitor](./delete-icmp-monitor) - [Trigger ICMP Check](./trigger-check-icmp-monitor) ### Create ICMP Monitor URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/create-icmp-monitor Description: Creates a new ICMP monitor. Summary: `POST /api/icmp-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Request Body ```json { "customerId": "6764e84f-f02a-43e6-a46d-cecaec556723", "name": "Ping Gateway", "hostname": "claas.sh", "status": "active", "checkInterval": 5, "timeoutSeconds": 10, "icmpConfig": { "packetSize": 56, "count": 4 } } ``` ### Fields - `customerId` (number | string, required) - Accepts the internal numeric customer ID or the customer `publicId` UUID. - `name` (string, required) - `hostname` (string, required) - Must be a hostname or IP only (no protocol like `https://`, no path like `/ping`). - `status` (string, optional) - Allowed: `active`, `maintenance`, `disabled`, `paused`, `inactive` - Note: `paused` / `inactive` are normalized to `disabled`. - `checkInterval` (number, optional) - `timeoutSeconds` (number, optional) - `icmpConfig` (object, optional) - Stored as the monitor's `config` JSON. ### `icmpConfig` (worker-supported keys) - `packetSize` (number) - Default: `56` - `count` (number) - Default: `3` ## cURL ```bash curl -X POST "https://YOUR_DOMAIN/api/icmp-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": "6764e84f-f02a-43e6-a46d-cecaec556723", "name": "Ping Gateway", "hostname": "claas.sh", "status": "active", "checkInterval": 5, "timeoutSeconds": 10, "icmpConfig": { "packetSize": 56, "count": 4 } }' ``` ## Response ```json { "id": 123, "organizationId": 1, "customerId": 2, "name": "Ping Gateway", "hostname": "claas.sh", "port": null, "status": "active", "checkInterval": 5, "timeoutSeconds": 10, "allowedCheckCountryCodes": null, "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "config": { "packetSize": 56, "count": 4 }, "icmpConfig": { "packetSize": 56, "count": 4 } } ``` ## Errors - `400 Invalid Customer identifier` - `400` Invalid hostname or invalid request body - `401` Unauthorized - `403` Forbidden (e.g. `readonly` or global supporter) - `404` Customer not found ### Delete ICMP Monitor URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/delete-icmp-monitor Description: Deletes an ICMP monitor. Summary: `DELETE /api/icmp-monitors/:icmpMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. ## cURL ```bash curl -X DELETE "https://YOUR_DOMAIN/api/icmp-monitors/22222222-2222-4222-8222-222222222222" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true } ``` ## Errors - `400` ICMP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` ICMP monitor not found ### Get ICMP Monitor URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/get-icmp-monitor Description: Returns details of a specific ICMP monitor. Summary: `GET /api/icmp-monitors/:icmpMonitorPublicId` The response contains the ICMP monitor itself and does not embed the full customer record. ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. ## cURL ```bash curl "https://YOUR_DOMAIN/api/icmp-monitors/22222222-2222-4222-8222-222222222222" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "id": 123, "organizationId": 1, "customerId": 10, "name": "Core Router", "hostname": "10.0.0.1", "port": null, "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "config": { "packetSize": 56, "count": 3 }, "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "icmpConfig": { "packetSize": 56, "count": 3 } } ``` ## Errors - `400` ICMP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` ICMP monitor not found ### Get ICMP Monitor Alert History URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/get-icmp-monitor-alert-history Description: Returns notification/escalation attempts (alert history) for incidents of a ICMP monitor. Summary: `GET /api/icmp-monitors/:icmpMonitorPublicId/alert-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/icmp-monitors/11111111-1111-4111-8111-111111111111/alert-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "alerts": [ { "id": 987, "incidentId": 123, "type": "slack", "status": "sent", "channelName": "Ops Slack", "sentAt": "2026-02-26T12:11:00.000Z", "errorMessage": null } ], "total": 1 } ``` Each entry is one delivery attempt to one notification channel. `status` is `sent` or `failed` (with `errorMessage` set on failure); `type` is the channel type (e.g. `email`, `slack`, `opsgenie`). ## Common Errors - `400 ICMP monitor public ID (UUID) required` if `:icmpMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### Get ICMP Monitor Check History URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/get-icmp-monitor-check-history Description: Returns recent check results for the ICMP monitor. Summary: `GET /api/icmp-monitors/:icmpMonitorPublicId/check-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. - `limit` (Query, optional): Maximum number of results (default: 50, max: 200). ## cURL ```bash curl -X GET "https://YOUR_DOMAIN/api/icmp-monitors/22222222-2222-4222-8222-222222222222/check-history?limit=50" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "data": [ { "id": "f6b0e5a7-4c4a-4d3b-9f6b-0e5a74c4a4d3", "status": "success", "errorMessage": null, "warningMessage": null, "timingIcmp": 22, "diagnostics": { "min": 11.1, "avg": 22.2, "max": 33.3, "packetLoss": 0 }, "checkedAt": "2026-02-26T12:00:00.000Z", "locationId": 7, "locationName": "Nuremberg (DE)", "locationCode": "de-nbg" } ] } ``` ## Errors - `400` ICMP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` ICMP monitor not found ### Get ICMP Monitor Details URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/get-icmp-monitor-details Description: Returns a consolidated payload used by the monitor details page, including the monitor, customer, and aggregated check data for a given time range. Summary: `GET /api/icmp-monitors/:icmpMonitorPublicId/details` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. ### Time range query parameters The endpoint supports multiple ways to define the time range. Use the simplest option for your use case: - `range` (Query, optional): Preset range. - Allowed: `day` (default), `week`, `month`, `year` - `date` (Query, optional): Reference date used as the default end date. - Example: `2026-02-26` - `startDate` (Query, optional): Start date/time. - `endDate` (Query, optional): End date/time. - `granularity` (Query, optional): Controls aggregation. - Use `raw` to disable aggregation. - Any other value enables aggregation. - If omitted, the server may aggregate automatically for larger ranges. If you provide multiple, the server resolves them according to its internal precedence rules. ## cURL ```bash curl -X GET "https://YOUR_DOMAIN/api/icmp-monitors/22222222-2222-4222-8222-222222222222/details?range=day&granularity=raw" \ -H "Authorization: Bearer $TOKEN" ``` ## Response Top-level fields (current shape): - `icmpMonitorId` - `monitor` - `latestCheck` - `uptimeStats`, `uptimeStatsMeta` - `monitoringData` - `incidents` - `alerts` - `testResultLog` - `maintenance` Example: ```json { "icmpMonitorId": 123, "monitor": { "id": 123, "customerId": 10, "organizationId": 1, "name": "Core Router", "hostname": "10.0.0.1", "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "port": null, "config": { "packetSize": 56, "count": 3 }, "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z" }, "latestCheck": null, "uptimeStats": { "day": "100.00", "month": "100.00", "year": "100.00", "dayAvgResponse": 22, "monthAvgResponse": 22, "yearAvgResponse": 22 }, "uptimeStatsMeta": { "day": { "window": "24h", "downtimeMinutes": 0, "incidents": 0, "checksTotal": 24, "checksFailed": 0 }, "month": { "window": "30d", "downtimeMinutes": 0, "incidents": 0, "checksTotal": 720, "checksFailed": 0 }, "year": { "window": "YTD", "downtimeMinutes": 0, "incidents": 0, "checksTotal": 1000, "checksFailed": 0 } }, "monitoringData": { "responseTimeData": [ { "timestamp": "2026-02-26T12:00:00.000Z", "responseTime": 22, "status": "success", "success": true, "timingDns": 0, "timingTcp": 22, "timingTls": 0, "timingTtfb": 0, "timingTransfer": 0 } ], "statusData": [{ "date": "26.02", "status": "online" }], "uptimePercentage": "100.00", "checkSuccessRatePercentage": "100.00", "totalChecks": 100, "successfulChecks": 100 }, "incidents": { "history": [], "total": 0, "ongoing": 0, "totalDowntime": "0s" }, "alerts": { "history": [], "total": 0, "notificationContext": { "orgDefaultEmail": null, "orgDefaultPhoneNumber": null, "customerEmail": null, "notificationTargets": [] } }, "testResultLog": [], "maintenance": { "inMaintenance": false, "activeWindows": [], "allWindows": [] } } ``` ## Errors - `400` ICMP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` ICMP monitor not found - `500` Failed to fetch ICMP monitor details ### Get ICMP Monitor Incident History URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/get-icmp-monitor-incident-history Description: Returns incidents for a single ICMP monitor (latest 100), including a computed duration. Summary: `GET /api/icmp-monitors/:icmpMonitorPublicId/incident-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/icmp-monitors/11111111-1111-4111-8111-111111111111/incident-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "incidents": [ { "id": 123, "type": "downtime", "status": "resolved", "startedAt": "Feb 26, 2026, 12:10:00", "endedAt": "Feb 26, 2026, 12:12:30", "duration": "2m 30s" } ], "total": 1 } ``` `type` reflects the failure category for this monitor; `status` is `active` (ongoing) or `resolved`. Ongoing incidents have a `null` `endedAt`. ## Common Errors - `400 ICMP monitor public ID (UUID) required` if `:icmpMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### List ICMP Monitors URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/list-icmp-monitors Description: Lists ICMP monitors in an organization. Summary: `GET /api/icmp-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `organizationId` (Query, optional): Organization ID. Defaults to the current user's organization. - `customerId` (Query, optional): Filter by customer ID. - `search` (Query, optional): Search by monitor name, hostname, or customer. - `page` (Query, optional): Page number (default: 1). - `perPage` (Query, optional): Items per page (default: 50, max: 200). ## cURL ```bash curl "https://YOUR_DOMAIN/api/icmp-monitors?page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "items": [ { "id": 123, "organizationId": 1, "customerId": 10, "customerName": "Example Customer", "name": "Core Router", "hostname": "10.0.0.1", "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "port": null, "config": { "packetSize": 56, "count": 3 }, "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z" } ], "total": 1, "page": 1, "perPage": 50 } ``` Each item contains the ICMP monitor itself and a flat `customerName`, not a full embedded customer record. ## Errors - `400` Invalid query parameters (e.g. `organizationId`, `customerId`) - `401` Unauthorized - `403` Forbidden ### Trigger ICMP Check URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/trigger-check-icmp-monitor Description: Triggers an immediate check from all eligible monitoring locations. Summary: `POST /api/icmp-monitors/:icmpMonitorPublicId/trigger-check` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. ## cURL ```bash curl -X POST "https://YOUR_DOMAIN/api/icmp-monitors/22222222-2222-4222-8222-222222222222/trigger-check" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true, "message": "Checks triggered successfully", "icmpMonitorId": 123, "locationCodes": ["de-nbg", "fi-hel"], "queueNames": ["icmp-monitor-checks-de-nbg", "icmp-monitor-checks-fi-hel"] } ``` ## Errors - `400` ICMP monitor public ID (UUID) required or no eligible locations - `401` Unauthorized - `403` Forbidden - `404` ICMP monitor not found - `503` No active monitoring locations available - `500` Failed to trigger check ### Update ICMP Monitor URL: https://docs.uptimeify.io/api/monitors/icmp-monitors/update-icmp-monitor Description: Updates an ICMP monitor. This endpoint is also used to change the monitor status. Summary: `PATCH /api/icmp-monitors/:icmpMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `icmpMonitorPublicId` (Path, required): ICMP monitor public UUID. ## Request Body All fields are optional. - `status` (optional) - Allowed: `active`, `maintenance`, `disabled`, `paused`, `inactive` - Note: `paused` / `inactive` are normalized to `disabled`. - `name`, `hostname`, `checkInterval`, `timeoutSeconds` (optional) - `port` (optional) - Supported by the API, but currently not used by the ICMP worker. - `allowedCheckCountryCodes` (optional) - Normalized to upper-case and de-duplicated. - `icmpConfig` (optional) - Alias for the stored `config` JSON. - `config` (optional) - Alternative way to update the same stored `config` JSON. Note: Read-only users may only change `status` (and sending any other fields will result in `403`). ```json { "status": "maintenance", "allowedCheckCountryCodes": ["DE", "CH"] } ``` Example updating config: ```json { "icmpConfig": { "packetSize": 56, "count": 3 } } ``` ## cURL ```bash curl -X PATCH "https://YOUR_DOMAIN/api/icmp-monitors/22222222-2222-4222-8222-222222222222" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "status": "disabled" }' ``` ## Response ```json { "id": 123, "organizationId": 1, "customerId": 10, "name": "Core Router", "hostname": "10.0.0.1", "port": null, "status": "maintenance", "checkInterval": 30, "timeoutSeconds": 30, "allowedCheckCountryCodes": ["DE", "CH"], "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:05:00.000Z", "config": { "packetSize": 56, "count": 3 }, "icmpConfig": { "packetSize": 56, "count": 3 } } ``` ## Errors - `400` Invalid request body, invalid status, or invalid hostname - `401` Unauthorized - `403` Forbidden (e.g. `readonly` or global supporter) - `404` ICMP monitor not found ### IMAP/POP Monitors URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors Description: Manage IMAP/POP monitors. Summary: Path-based IMAP/POP monitor endpoints use `imapPopMonitorPublicId` UUIDs. ## Endpoints - [List IMAP/POP Monitors](./list-imap-pop-monitors) - [Create IMAP/POP Monitor](./create-imap-pop-monitor) - [Get IMAP/POP Monitor](./get-imap-pop-monitor) - [Update IMAP/POP Monitor](./update-imap-pop-monitor) - [Delete IMAP/POP Monitor](./delete-imap-pop-monitor) - [Trigger IMAP/POP Check](./trigger-check-imap-pop-monitor) - [Get IMAP/POP Monitor Details](./get-imap-pop-monitor-details) - [Get IMAP/POP Monitor Check History](./get-imap-pop-monitor-check-history) ### Create IMAP/POP Monitor URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/create-imap-pop-monitor Description: Creates a new IMAP/POP monitor. Summary: `POST /api/imap-pop-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Request Body ```json { "customerId": "11111111-1111-4111-8111-111111111111", "name": "Mailbox Access", "hostname": "mail.example.com", "port": 993, "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "imapPopConfig": { "protocol": "imap", "user": "monitor@example.com", "password": "password", "tls": true, "tlsOptions": { "rejectUnauthorized": true } } } ``` ### Fields - `customerId` (number | string, required) - Accepts either the internal numeric customer ID or the public customer UUID. - `name` (string, required) - `hostname` (string, required) - Must be a hostname only (no protocol like `https://`, no path like `/imap`). - `port` (number | null, optional) - If omitted or `null`, the worker chooses a default port depending on `imapPopConfig.protocol` and `imapPopConfig.tls`. - `status` (string, optional) - Allowed: `active`, `maintenance`, `disabled`, `paused`, `inactive` - Note: `paused` / `inactive` are normalized to `disabled`. - `checkInterval` (number, optional) - `timeoutSeconds` (number, optional) - `imapPopConfig` (object, optional) - Stored as the monitor's `config` JSON. ### `imapPopConfig` (worker-supported keys) - `protocol` (`imap` | `pop3`) - Default: `imap` - `user` (string) - `password` (string) - `tls` (boolean) - Default: `false` - `tlsOptions.rejectUnauthorized` (boolean) - Used by the IMAP worker library; POP3 currently ignores this option. ### Default ports (worker behavior) If `port` is omitted or `null`: - IMAP: - TLS (`tls: true`): `993` - Non-TLS (`tls: false`): `143` - POP3: - TLS (`tls: true`): `995` - Non-TLS (`tls: false`): `110` ## cURL ```bash curl -X POST "https://YOUR_DOMAIN/api/imap-pop-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": "11111111-1111-4111-8111-111111111111", "name": "Mailbox Access", "hostname": "mail.example.com", "port": 993, "status": "active", "checkInterval": 30, "timeoutSeconds": 30, "imapPopConfig": { "protocol": "imap", "user": "monitor@example.com", "password": "password", "tls": true } }' ``` ## Response ```json { "id": 500, "organizationId": 1, "customerId": 10, "name": "Mailbox Access", "hostname": "mail.example.com", "port": 993, "checkInterval": 30, "timeoutSeconds": 30, "status": "active", "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "config": { "protocol": "imap", "user": "monitor@example.com", "password": "password", "tls": true }, "imapPopConfig": { "protocol": "imap", "user": "monitor@example.com", "password": "password", "tls": true } } ``` ## Errors - `400` Invalid hostname or invalid request body - `400` Invalid Customer identifier - `401` Unauthorized - `403` Forbidden (e.g. `readonly` or global supporter) - `404` Customer not found ### Delete IMAP/POP Monitor URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/delete-imap-pop-monitor Description: Deletes an IMAP/POP monitor. Summary: `DELETE /api/imap-pop-monitors/:imapPopMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. ## Response ```json { "success": true } ``` ## Errors - `400` IMAP/POP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden (e.g. `readonly` or global supporter) - `404` IMAP/POP monitor not found ### Get IMAP/POP Monitor URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/get-imap-pop-monitor Description: Returns details of a specific IMAP/POP monitor. Summary: `GET /api/imap-pop-monitors/:imapPopMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. ## Response ```json { "id": 500, "organizationId": 1, "customerId": 10, "name": "Mailbox Access", "hostname": "mail.example.com", "port": 993, "checkInterval": 30, "timeoutSeconds": 30, "config": { "protocol": "imap", "user": "monitor@example.com", "password": "password", "tls": true }, "allowedCheckCountryCodes": null, "status": "active", "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "customer": { "id": 10, "organizationId": 1, "name": "Example Customer", "email": "ops@example.com", "allowedCheckCountryCodes": null, "customFields": null, "alertLocationThresholdCount": 1, "createdAt": "2026-02-01T12:00:00.000Z", "updatedAt": "2026-02-01T12:00:00.000Z" }, "imapPopConfig": { "protocol": "imap", "user": "monitor@example.com", "password": "password", "tls": true } } ``` ## Errors - `400` IMAP/POP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` IMAP/POP monitor not found ### Get IMAP/POP Monitor Alert History URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/get-imap-pop-monitor-alert-history Description: Returns notification/escalation attempts (alert history) for incidents of a IMAP/POP monitor. Summary: `GET /api/imap-pop-monitors/:imapPopMonitorPublicId/alert-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/imap-pop-monitors/11111111-1111-4111-8111-111111111111/alert-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "alerts": [ { "id": 987, "incidentId": 123, "type": "slack", "status": "sent", "channelName": "Ops Slack", "sentAt": "2026-02-26T12:11:00.000Z", "errorMessage": null } ], "total": 1 } ``` Each entry is one delivery attempt to one notification channel. `status` is `sent` or `failed` (with `errorMessage` set on failure); `type` is the channel type (e.g. `email`, `slack`, `opsgenie`). ## Common Errors - `400 IMAP/POP monitor public ID (UUID) required` if `:imapPopMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### Get IMAP/POP Monitor Check History URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/get-imap-pop-monitor-check-history Description: Returns recent check results for the IMAP/POP monitor. Summary: `GET /api/imap-pop-monitors/:imapPopMonitorPublicId/check-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. - `limit` (Query, optional): Maximum number of results (default: 50, max: 200). ## cURL ```bash curl -X GET "https://YOUR_DOMAIN/api/imap-pop-monitors/66666666-6666-4666-8666-666666666666/check-history?limit=50" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "data": [ { "id": 123, "status": "success", "errorMessage": null, "warningMessage": null, "timingImapPop": 142, "diagnostics": { "message": "IMAP connection successful" }, "checkedAt": "2026-02-26T12:00:00.000Z", "locationId": 7, "locationName": "Nuremberg (DE)", "locationCode": "de-nbg" } ] } ``` ## Errors - `400` IMAP/POP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` IMAP/POP monitor not found ### Get IMAP/POP Monitor Details URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/get-imap-pop-monitor-details Description: Consolidated endpoint that returns the IMAP/POP monitor detail page payload in a single call (latest check, uptime stats, incidents, alert history, maintenance windows, chart data, etc.). Summary: `GET /api/imap-pop-monitors/:imapPopMonitorPublicId/details` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. - `range` (Query, optional): `day` | `week` | `month` | `year` (default: `day`). - `date` (Query, optional): Reference date as ISO string. - `startDate` (Query, optional): Override start date as ISO string. - `endDate` (Query, optional): Override end date as ISO string. - `granularity` (Query, optional): If set and not `raw`, the backend may aggregate monitoring chart data. ## cURL ```bash curl -X GET "https://YOUR_DOMAIN/api/imap-pop-monitors/66666666-6666-4666-8666-666666666666/details?range=day" \ -H "Authorization: Bearer $TOKEN" ``` ## Response The response is a large object. Key top-level fields: - `imapPopMonitorId` - `monitor` - `latestCheck` - `uptimeStats`, `uptimeStatsMeta` - `monitoringData` - `incidents` - `alerts` - `testResultLog` - `maintenance` Example (truncated): ```json { "imapPopMonitorId": 500, "monitor": { "id": 500, "hostname": "mail.example.com", "status": "active" }, "latestCheck": { "id": 123, "status": "success", "checkedAt": "2026-02-26T12:00:00.000Z" }, "uptimeStats": { "day": "100.00", "month": "100.00", "year": "100.00", "dayAvgResponse": 142, "monthAvgResponse": 150, "yearAvgResponse": 160 }, "maintenance": { "inMaintenance": false, "activeWindows": [], "allWindows": [] } } ``` ## Errors - `400` Invalid IMAP/POP monitor public ID (UUID) - `401` Unauthorized - `403` Forbidden - `404` IMAP/POP monitor not found - `500` Failed to fetch IMAP/POP monitor details ### Get IMAP/POP Monitor Incident History URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/get-imap-pop-monitor-incident-history Description: Returns incidents for a single IMAP/POP monitor (latest 100), including a computed duration. Summary: `GET /api/imap-pop-monitors/:imapPopMonitorPublicId/incident-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/imap-pop-monitors/11111111-1111-4111-8111-111111111111/incident-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "incidents": [ { "id": 123, "type": "downtime", "status": "resolved", "startedAt": "Feb 26, 2026, 12:10:00", "endedAt": "Feb 26, 2026, 12:12:30", "duration": "2m 30s" } ], "total": 1 } ``` `type` reflects the failure category for this monitor; `status` is `active` (ongoing) or `resolved`. Ongoing incidents have a `null` `endedAt`. ## Common Errors - `400 IMAP/POP monitor public ID (UUID) required` if `:imapPopMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### List IMAP/POP Monitors URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/list-imap-pop-monitors Description: Lists IMAP/POP monitors in an organization. Summary: `GET /api/imap-pop-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `organizationId` (Query, optional): Organization ID. Defaults to the current user's organization. - `customerId` (Query, optional): Filter by customer ID. - `search` (Query, optional): Search by monitor name, hostname, or customer. - `page` (Query, optional): Page number (default: 1). - `perPage` (Query, optional): Items per page (default: 50, max: 200). ## Response ```json { "items": [ { "id": 500, "organizationId": 1, "customerId": 10, "name": "Mailbox Access", "hostname": "mail.example.com", "port": 993, "checkInterval": 30, "timeoutSeconds": 30, "customerName": "Example Customer", "config": { "protocol": "imap", "user": "monitor@example.com", "password": "password", "tls": true }, "status": "active", "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z" } ], "total": 1, "page": 1, "perPage": 50 } ``` ## Errors - `400` Invalid query parameters (e.g. `organizationId`, `customerId`) - `401` Unauthorized - `403` Forbidden ### Trigger IMAP/POP Check URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/trigger-check-imap-pop-monitor Description: Triggers an immediate check from all eligible monitoring locations. Summary: `POST /api/imap-pop-monitors/:imapPopMonitorPublicId/trigger-check` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. ## Response ```json { "success": true, "message": "Checks triggered successfully", "imapPopMonitorId": 500, "locationCodes": ["de-nbg", "fi-hel"], "queueNames": ["imap-pop-monitor-checks-de-nbg", "imap-pop-monitor-checks-fi-hel"] } ``` ## Errors - `400` Invalid IMAP/POP monitor public ID (UUID) or no eligible locations - `401` Unauthorized - `403` Forbidden - `404` IMAP/POP monitor not found - `503` No active monitoring locations available - `500` Failed to trigger check ### Update IMAP/POP Monitor URL: https://docs.uptimeify.io/api/monitors/imap-pop-monitors/update-imap-pop-monitor Description: Updates an IMAP/POP monitor and/or changes its status. Summary: `PATCH /api/imap-pop-monitors/:imapPopMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `imapPopMonitorPublicId` (Path, required): IMAP/POP monitor public UUID. ## Request Body - `status` (optional) - Allowed: `active`, `maintenance`, `disabled`, `paused`, `inactive` - Note: `paused` / `inactive` are normalized to `disabled`. - `name`, `hostname`, `port`, `checkInterval`, `timeoutSeconds` (optional) - `allowedCheckCountryCodes` (optional) - Normalized to upper-case and de-duplicated. - `imapPopConfig` (optional) - Alias for the stored `config` JSON. - `config` (optional) - Alternative way to update the same stored `config` JSON. Note: Read-only users may only change `status` (and sending any other fields will result in `403`). ```json { "status": "active" } ``` Example updating config: ```json { "imapPopConfig": { "protocol": "pop3", "tls": true, "user": "monitor@example.com", "password": "password" } } ``` ## Response ```json { "id": 500, "organizationId": 1, "customerId": 10, "name": "Mailbox Access", "hostname": "mail.example.com", "port": 993, "checkInterval": 30, "timeoutSeconds": 30, "status": "active", "notificationPhoneNumber": null, "notificationEmail": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:05:00.000Z", "config": { "protocol": "pop3", "tls": true, "user": "monitor@example.com", "password": "password" }, "imapPopConfig": { "protocol": "pop3", "tls": true, "user": "monitor@example.com", "password": "password" } } ``` ## Errors - `400` Invalid request body, invalid status, or invalid hostname - `401` Unauthorized - `403` Forbidden (e.g. `readonly` or global supporter) - `404` IMAP/POP monitor not found ### SMTP Monitors URL: https://docs.uptimeify.io/api/monitors/smtp-monitors Description: Manage SMTP monitors. Summary: Path-based SMTP monitor endpoints use `smtpMonitorPublicId` UUIDs. ## Endpoints - [List SMTP Monitors](./list-smtp-monitors) - [Create SMTP Monitor](./create-smtp-monitor) - [Get SMTP Monitor](./get-smtp-monitor) - [Get SMTP Monitor Details](./get-smtp-monitor-details) - [Get SMTP Monitor Check History](./get-smtp-monitor-check-history) - [Update SMTP Monitor](./update-smtp-monitor) - [Delete SMTP Monitor](./delete-smtp-monitor) - [Trigger Check for SMTP Monitor](./trigger-check-smtp-monitor) ### Create SMTP Monitor URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/create-smtp-monitor Description: Creates a new SMTP monitor. Summary: `POST /api/smtp-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Request Body ```json { "customerId": "11111111-1111-4111-8111-111111111111", "name": "Outbound SMTP", "hostname": "smtp.example.com", "port": 587, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "smtpConfig": { "secure": false, "ignoreTls": false, "requireTls": false, "auth": { "user": "username", "pass": "password" } } } ``` ### Fields - `customerId` (number | string, required) - Accepts either the internal numeric customer ID or the public customer UUID. - `name` (string, required) - `hostname` (string, required) - Must be a hostname only (no protocol like `https://`, no path like `/smtp`). - `port` (number | null, optional) - If omitted or `null`, the worker defaults to `465` when `smtpConfig.secure=true`, otherwise `25`. - `status` (string, optional) - Allowed: `active`, `maintenance`, `disabled`, `paused`, `inactive` - `checkInterval` (number, optional) - `timeoutSeconds` (number, optional) - `smtpConfig` (object, optional) - Stored as the monitor's `config` JSON. ### `smtpConfig` (worker-supported keys) The SMTP worker coerces/uses these keys: - `secure` (boolean, default `false`) - `ignoreTls` (boolean, default `false`) - `requireTls` (boolean, default `false`) - `auth.user` and `auth.pass` (strings) - Credentials are only used when *both* `user` and `pass` are provided. ## cURL ```bash curl -X POST "https://YOUR_DOMAIN/api/smtp-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": "11111111-1111-4111-8111-111111111111", "name": "Outbound SMTP", "hostname": "smtp.example.com", "port": 587, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "smtpConfig": { "secure": false, "ignoreTls": false, "requireTls": false, "auth": { "user": "username", "pass": "password" } } }' ``` ## Response ```json { "id": 200, "organizationId": 1, "customerId": 10, "name": "Outbound SMTP", "hostname": "smtp.example.com", "port": 587, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": null, "createdAt": "2026-01-01T12:00:00.000Z", "updatedAt": "2026-01-01T12:00:00.000Z", "config": { "secure": false, "ignoreTls": false, "requireTls": false, "auth": { "user": "username", "pass": "password" } }, "smtpConfig": { "secure": false, "ignoreTls": false, "requireTls": false, "auth": { "user": "username", "pass": "password" } } } ``` ## Errors - `400` Invalid hostname or invalid request body - `400` Invalid Customer identifier - `401` Unauthorized - `403` Forbidden (e.g. `readonly` or global supporter) ### Delete SMTP Monitor URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/delete-smtp-monitor Description: Deletes an SMTP monitor. Summary: `DELETE /api/smtp-monitors/:smtpMonitorPublicId` ## Authentication Requires a valid session and write access. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## cURL ```bash curl -X DELETE "https://YOUR_DOMAIN/api/smtp-monitors/33333333-3333-4333-8333-333333333333" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true } ``` ## Errors - `400` SMTP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found ### Get SMTP Monitor URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/get-smtp-monitor Description: Returns details of a specific SMTP monitor. Summary: `GET /api/smtp-monitors/:smtpMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## cURL ```bash curl "https://YOUR_DOMAIN/api/smtp-monitors/33333333-3333-4333-8333-333333333333" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "id": 200, "organizationId": 1, "customerId": 10, "name": "Outbound SMTP", "hostname": "smtp.example.com", "port": 587, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "customerName": "Example Customer", "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": "2026-01-01T12:00:00.000Z", "createdAt": "2026-01-01T12:00:00.000Z", "updatedAt": "2026-01-01T12:00:00.000Z", "config": { "secure": false, "ignoreTls": false, "requireTls": false }, "smtpConfig": { "secure": false, "ignoreTls": false, "requireTls": false } } ``` ## Errors - `400` SMTP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found ### Get SMTP Monitor Alert History URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/get-smtp-monitor-alert-history Description: Returns notification/escalation attempts (alert history) for incidents of a SMTP monitor. Summary: `GET /api/smtp-monitors/:smtpMonitorPublicId/alert-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/smtp-monitors/11111111-1111-4111-8111-111111111111/alert-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "alerts": [ { "id": 987, "incidentId": 123, "type": "slack", "status": "sent", "channelName": "Ops Slack", "sentAt": "2026-02-26T12:11:00.000Z", "errorMessage": null } ], "total": 1 } ``` Each entry is one delivery attempt to one notification channel. `status` is `sent` or `failed` (with `errorMessage` set on failure); `type` is the channel type (e.g. `email`, `slack`, `opsgenie`). ## Common Errors - `400 SMTP monitor public ID (UUID) required` if `:smtpMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### Get SMTP Monitor Check History URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/get-smtp-monitor-check-history Description: Returns recent check results for an SMTP monitor. Summary: `GET /api/smtp-monitors/:smtpMonitorPublicId/check-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## Query Parameters - `limit` (number, optional) - Default: `50` - Max: `200` ## cURL ```bash curl "https://YOUR_DOMAIN/api/smtp-monitors/33333333-3333-4333-8333-333333333333/check-history?limit=50" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "data": [ { "id": 12345, "status": "success", "errorMessage": null, "warningMessage": null, "timingSmtp": 123, "diagnostics": { "raw": "optional diagnostic payload" }, "checkedAt": "2026-01-01T12:00:00.000Z", "locationId": 7, "locationName": "Nuremberg (DE)", "locationCode": "de-nbg" } ] } ``` ## Errors - `400` SMTP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found ### Get SMTP Monitor Details URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/get-smtp-monitor-details Description: Consolidated endpoint that returns the SMTP monitor details page data in one call. Summary: `GET /api/smtp-monitors/:smtpMonitorPublicId/details` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## Query Parameters - `range` (string, optional): `day`, `week`, `month`, `year` (default: `day`) - `date` (string, optional): Reference date (parsed by `new Date(date)`) - `startDate` (string, optional) - `endDate` (string, optional) - `granularity` (string, optional) - If set to `raw`, disables aggregation. ## cURL ```bash curl "https://YOUR_DOMAIN/api/smtp-monitors/33333333-3333-4333-8333-333333333333/details?range=day" \ -H "Authorization: Bearer $TOKEN" ``` ## Response The response is a single object with these top-level keys: - `smtpMonitorId` - `monitor` - `latestCheck` - `uptimeStats` - `uptimeStatsMeta` - `monitoringData` - `incidents` - `alerts` - `testResultLog` - `maintenance` Example (truncated): ```json { "smtpMonitorId": 200, "monitor": { "id": 200, "customerId": 10, "name": "Outbound SMTP", "hostname": "smtp.example.com", "port": 587, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "config": { "secure": false, "requireTls": true } }, "latestCheck": { "status": "success", "checkedAt": "2026-01-01T12:00:00.000Z", "timingSmtp": 123, "locationCode": "de-nbg", "locationName": "Nuremberg (DE)" }, "uptimeStats": { "day": 99.9, "month": 99.5, "year": 99.0, "dayAvgResponse": 120, "monthAvgResponse": 140, "yearAvgResponse": 150 }, "maintenance": { "inMaintenance": false, "activeWindows": [], "allWindows": [] } } ``` ## Errors - `400` Invalid SMTP monitor public ID (UUID) - `401` Unauthorized - `403` Forbidden - `404` Not found - `500` Failed to fetch SMTP monitor details ### Get SMTP Monitor Incident History URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/get-smtp-monitor-incident-history Description: Returns incidents for a single SMTP monitor (latest 100), including a computed duration. Summary: `GET /api/smtp-monitors/:smtpMonitorPublicId/incident-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/smtp-monitors/11111111-1111-4111-8111-111111111111/incident-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "incidents": [ { "id": 123, "type": "downtime", "status": "resolved", "startedAt": "Feb 26, 2026, 12:10:00", "endedAt": "Feb 26, 2026, 12:12:30", "duration": "2m 30s" } ], "total": 1 } ``` `type` reflects the failure category for this monitor; `status` is `active` (ongoing) or `resolved`. Ongoing incidents have a `null` `endedAt`. ## Common Errors - `400 SMTP monitor public ID (UUID) required` if `:smtpMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### List SMTP Monitors URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/list-smtp-monitors Description: Lists SMTP monitors in an organization. Summary: `GET /api/smtp-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `organizationId` (Query, optional): Organization ID. Defaults to the current user's organization. - `customerId` (Query, optional): Filter by customer ID. - `search` (Query, optional): Search by monitor name, hostname, or customer. - `page` (Query, optional): Page number (default: 1). - `perPage` (Query, optional): Items per page (default: 50, max: 200). ## cURL ```bash curl "https://YOUR_DOMAIN/api/smtp-monitors?page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "items": [ { "id": 200, "organizationId": 1, "customerId": 10, "name": "Outbound SMTP", "hostname": "smtp.example.com", "port": 587, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "customerName": "Example Customer", "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": "2026-01-01T12:00:00.000Z", "createdAt": "2026-01-01T12:00:00.000Z", "updatedAt": "2026-01-01T12:00:00.000Z", "config": { "secure": false, "ignoreTls": false, "requireTls": false } } ], "total": 1, "page": 1, "perPage": 50 } ``` ## Errors - `400` Invalid `organizationId` or `customerId` - `401` Unauthorized - `403` Forbidden ### Trigger Check for SMTP Monitor URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/trigger-check-smtp-monitor Description: Triggers an immediate check from all eligible monitoring locations. Summary: `POST /api/smtp-monitors/:smtpMonitorPublicId/trigger-check` ## Authentication Requires a valid session and write access. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## cURL ```bash curl -X POST "https://YOUR_DOMAIN/api/smtp-monitors/33333333-3333-4333-8333-333333333333/trigger-check" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true, "message": "Checks triggered successfully", "smtpMonitorId": 200, "locationCodes": ["de-nbg", "fi-hel"], "queueNames": ["smtp-monitor-checks-de-nbg", "smtp-monitor-checks-fi-hel"] } ``` ## Errors - `400` SMTP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found - `500` Failed to trigger check (the status message may include e.g. "No active monitoring locations available") ### Update SMTP Monitor URL: https://docs.uptimeify.io/api/monitors/smtp-monitors/update-smtp-monitor Description: Updates an SMTP monitor. Summary: `PATCH /api/smtp-monitors/:smtpMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `smtpMonitorPublicId` (Path, required): SMTP monitor public UUID. ## Request Body All fields are optional. ```json { "name": "Outbound SMTP (Primary)", "hostname": "smtp.example.com", "port": 587, "status": "paused", "checkInterval": 60, "timeoutSeconds": 30, "allowedCheckCountryCodes": ["de", "ch"], "smtpConfig": { "secure": false, "requireTls": true, "auth": { "user": "username", "pass": "password" } } } ``` ### Notes - `status` accepts `active`, `maintenance`, `disabled`, `paused`, `inactive`. - `paused` and `inactive` are normalized to `disabled`. - `allowedCheckCountryCodes` is normalized to uppercase ISO codes (e.g. `DE`, `US`). Empty lists become `null`. - SMTP config can be provided as `smtpConfig` or as `config` (alias). If neither is provided, the stored config is not changed. - Users with `readonly` role can only change `status`. ## cURL ```bash curl -X PATCH "https://YOUR_DOMAIN/api/smtp-monitors/33333333-3333-4333-8333-333333333333" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "status": "disabled" }' ``` ## Response ```json { "id": 200, "organizationId": 1, "customerId": 10, "name": "Outbound SMTP (Primary)", "hostname": "smtp.example.com", "port": 587, "status": "disabled", "checkInterval": 60, "timeoutSeconds": 30, "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": "2026-01-01T12:00:00.000Z", "createdAt": "2026-01-01T12:00:00.000Z", "updatedAt": "2026-01-01T12:01:00.000Z", "config": { "secure": false, "requireTls": true, "auth": { "user": "username", "pass": "password" } }, "smtpConfig": { "secure": false, "requireTls": true, "auth": { "user": "username", "pass": "password" } } } ``` ## Errors - `400` SMTP monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden (readonly users may only update `status`; global supporters cannot update) - `404` Not found ### SSH Monitors URL: https://docs.uptimeify.io/api/monitors/ssh-monitors Description: Manage SSH monitors. Summary: Path-based SSH monitor endpoints use `sshMonitorPublicId` UUIDs. ## Endpoints - [List SSH Monitors](./list-ssh-monitors) - [Create SSH Monitor](./create-ssh-monitor) - [Get SSH Monitor](./get-ssh-monitor) - [Get SSH Monitor Details](./get-ssh-monitor-details) - [Get SSH Monitor Check History](./get-ssh-monitor-check-history) - [Update SSH Monitor](./update-ssh-monitor) - [Delete SSH Monitor](./delete-ssh-monitor) - [Trigger Check for SSH Monitor](./trigger-check-ssh-monitor) ### Create SSH Monitor URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/create-ssh-monitor Description: Creates a new SSH monitor. Summary: `POST /api/ssh-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Request Body ```json { "customerId": "11111111-1111-4111-8111-111111111111", "name": "Bastion Host", "hostname": "ssh.example.com", "port": 22, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "sshConfig": { "username": "root", "password": "password", "privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----..." } } ``` ### Fields - `customerId` (number | string, required) - Accepts either the internal numeric customer ID or the public customer UUID. - `name` (string, required) - `hostname` (string, required) - Must be a hostname only (no protocol like `https://`, no path like `/ssh`). - `port` (number | null, optional) - If omitted or `null`, the worker defaults to port `22`. - `status` (string, optional) - Allowed: `active`, `maintenance`, `disabled`, `paused`, `inactive` - `checkInterval` (number, optional) - `timeoutSeconds` (number, optional) - `sshConfig` (object, optional) - Stored as the monitor's `config` JSON. ### `sshConfig` (worker-supported keys) - `username` (string) - If omitted, the worker uses `anonymous`. - `password` (string) - `privateKey` (string) ## cURL ```bash curl -X POST "https://YOUR_DOMAIN/api/ssh-monitors" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": "11111111-1111-4111-8111-111111111111", "name": "Bastion Host", "hostname": "ssh.example.com", "port": 22, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "sshConfig": { "username": "root", "password": "password" } }' ``` ## Response ```json { "id": 300, "organizationId": 1, "customerId": 10, "name": "Bastion Host", "hostname": "ssh.example.com", "port": 22, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "config": { "username": "root", "password": "password" }, "sshConfig": { "username": "root", "password": "password" } } ``` ## Errors - `400` Invalid hostname or invalid request body - `400` Invalid Customer identifier - `401` Unauthorized - `403` Forbidden (e.g. `readonly` or global supporter) ### Delete SSH Monitor URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/delete-ssh-monitor Description: Deletes an SSH monitor. Summary: `DELETE /api/ssh-monitors/:sshMonitorPublicId` ## Authentication Requires a valid session and write access. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## cURL ```bash curl -X DELETE "https://YOUR_DOMAIN/api/ssh-monitors/44444444-4444-4444-8444-444444444444" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true } ``` ## Errors - `400` SSH monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found ### Get SSH Monitor URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/get-ssh-monitor Description: Returns details of a specific SSH monitor. Summary: `GET /api/ssh-monitors/:sshMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## cURL ```bash curl "https://YOUR_DOMAIN/api/ssh-monitors/44444444-4444-4444-8444-444444444444" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "id": 300, "organizationId": 1, "customerId": 10, "name": "Bastion Host", "hostname": "ssh.example.com", "port": 22, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "customerName": "Example Customer", "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": "2026-02-26T12:00:00.000Z", "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "config": { "username": "root" }, "sshConfig": { "username": "root" } } ``` ## Errors - `400` SSH monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found ### Get SSH Monitor Alert History URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/get-ssh-monitor-alert-history Description: Returns notification/escalation attempts (alert history) for incidents of a SSH monitor. Summary: `GET /api/ssh-monitors/:sshMonitorPublicId/alert-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/ssh-monitors/11111111-1111-4111-8111-111111111111/alert-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "alerts": [ { "id": 987, "incidentId": 123, "type": "slack", "status": "sent", "channelName": "Ops Slack", "sentAt": "2026-02-26T12:11:00.000Z", "errorMessage": null } ], "total": 1 } ``` Each entry is one delivery attempt to one notification channel. `status` is `sent` or `failed` (with `errorMessage` set on failure); `type` is the channel type (e.g. `email`, `slack`, `opsgenie`). ## Common Errors - `400 SSH monitor public ID (UUID) required` if `:sshMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### Get SSH Monitor Check History URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/get-ssh-monitor-check-history Description: Returns recent check results for an SSH monitor. Summary: `GET /api/ssh-monitors/:sshMonitorPublicId/check-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## Query Parameters - `limit` (number, optional) - Default: `50` - Max: `200` ## cURL ```bash curl "https://YOUR_DOMAIN/api/ssh-monitors/44444444-4444-4444-8444-444444444444/check-history?limit=50" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "data": [ { "id": 12345, "status": "success", "errorMessage": null, "warningMessage": null, "timingSsh": 123, "diagnostics": { "message": "SSH connection successful" }, "checkedAt": "2026-02-26T12:00:00.000Z", "locationId": 7, "locationName": "Nuremberg (DE)", "locationCode": "de-nbg" } ] } ``` ## Errors - `400` SSH monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found ### Get SSH Monitor Details URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/get-ssh-monitor-details Description: Consolidated endpoint that returns the SSH monitor details page data in one call. Summary: `GET /api/ssh-monitors/:sshMonitorPublicId/details` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## Query Parameters - `range` (string, optional): `day`, `week`, `month`, `year` (default: `day`) - `date` (string, optional): Reference date (parsed by `new Date(date)`) - `startDate` (string, optional) - `endDate` (string, optional) - `granularity` (string, optional) - If set to `raw`, disables aggregation. ## cURL ```bash curl "https://YOUR_DOMAIN/api/ssh-monitors/44444444-4444-4444-8444-444444444444/details?range=day" \ -H "Authorization: Bearer $TOKEN" ``` ## Response The response is a single object with these top-level keys: - `sshMonitorId` - `monitor` - `latestCheck` - `uptimeStats` - `uptimeStatsMeta` - `monitoringData` - `incidents` - `alerts` - `testResultLog` - `maintenance` Example (truncated): ```json { "sshMonitorId": 300, "monitor": { "id": 300, "customerId": 10, "name": "Bastion Host", "hostname": "ssh.example.com", "port": 22, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "config": { "username": "root" } }, "latestCheck": { "status": "success", "checkedAt": "2026-02-26T12:00:00.000Z", "timingSsh": 123, "locationCode": "de-nbg", "locationName": "Nuremberg (DE)" }, "uptimeStats": { "day": 99.9, "month": 99.5, "year": 99.0, "dayAvgResponse": 120, "monthAvgResponse": 140, "yearAvgResponse": 150 }, "maintenance": { "inMaintenance": false, "activeWindows": [], "allWindows": [] } } ``` ## Errors - `400` Invalid SSH monitor public ID (UUID) - `401` Unauthorized - `403` Forbidden - `404` Not found - `500` Failed to fetch SSH monitor details ### Get SSH Monitor Incident History URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/get-ssh-monitor-incident-history Description: Returns incidents for a single SSH monitor (latest 100), including a computed duration. Summary: `GET /api/ssh-monitors/:sshMonitorPublicId/incident-history` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/ssh-monitors/11111111-1111-4111-8111-111111111111/incident-history" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "incidents": [ { "id": 123, "type": "downtime", "status": "resolved", "startedAt": "Feb 26, 2026, 12:10:00", "endedAt": "Feb 26, 2026, 12:12:30", "duration": "2m 30s" } ], "total": 1 } ``` `type` reflects the failure category for this monitor; `status` is `active` (ongoing) or `resolved`. Ongoing incidents have a `null` `endedAt`. ## Common Errors - `400 SSH monitor public ID (UUID) required` if `:sshMonitorPublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access to the monitor ### List SSH Monitors URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/list-ssh-monitors Description: Lists SSH monitors in an organization. Summary: `GET /api/ssh-monitors` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `organizationId` (Query, optional): Organization ID. Defaults to the current user's organization. - `customerId` (Query, optional): Filter by customer ID. - `search` (Query, optional): Search by monitor name, hostname, or customer. - `page` (Query, optional): Page number (default: 1). - `perPage` (Query, optional): Items per page (default: 50, max: 200). ## cURL ```bash curl "https://YOUR_DOMAIN/api/ssh-monitors?page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "items": [ { "id": 300, "organizationId": 1, "customerId": 10, "name": "Bastion Host", "hostname": "ssh.example.com", "port": 22, "status": "active", "checkInterval": 60, "timeoutSeconds": 30, "customerName": "Example Customer", "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": "2026-02-26T12:00:00.000Z", "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "config": { "username": "root" } } ], "total": 1, "page": 1, "perPage": 50 } ``` ## Errors - `400` Invalid `organizationId` or `customerId` - `401` Unauthorized - `403` Forbidden ### Trigger Check for SSH Monitor URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/trigger-check-ssh-monitor Description: Triggers an immediate check from all eligible monitoring locations. Summary: `POST /api/ssh-monitors/:sshMonitorPublicId/trigger-check` ## Authentication Requires a valid session and write access. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## cURL ```bash curl -X POST "https://YOUR_DOMAIN/api/ssh-monitors/44444444-4444-4444-8444-444444444444/trigger-check" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true, "message": "Checks triggered successfully", "sshMonitorId": 300, "locationCodes": ["de-nbg", "fi-hel"], "queueNames": ["ssh-monitor-checks-de-nbg", "ssh-monitor-checks-fi-hel"] } ``` ## Errors - `400` SSH monitor public ID (UUID) required - `401` Unauthorized - `403` Forbidden - `404` Not found - `500` Failed to trigger check (the status message may include e.g. "No active monitoring locations available") ### Update SSH Monitor URL: https://docs.uptimeify.io/api/monitors/ssh-monitors/update-ssh-monitor Description: Updates an SSH monitor. Summary: `PATCH /api/ssh-monitors/:sshMonitorPublicId` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Parameters - `sshMonitorPublicId` (Path, required): SSH monitor public UUID. ## Request Body All fields are optional. ```json { "name": "Bastion Host (Primary)", "hostname": "ssh.example.com", "port": 22, "status": "paused", "checkInterval": 60, "timeoutSeconds": 30, "allowedCheckCountryCodes": ["de", "ch"], "sshConfig": { "username": "root", "privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----..." } } ``` ### Notes - `status` accepts `active`, `maintenance`, `disabled`, `paused`, `inactive`. - `paused` and `inactive` are normalized to `disabled`. - `allowedCheckCountryCodes` is normalized to uppercase ISO codes (e.g. `DE`, `US`). Empty lists become `null`. - SSH config can be provided as `sshConfig` or as `config` (alias). If neither is provided, the stored config is not changed. - Users with `readonly` role can only change `status`. ## cURL ```bash curl -X PATCH "https://YOUR_DOMAIN/api/ssh-monitors/44444444-4444-4444-8444-444444444444" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "status": "disabled" }' ``` ## Response ```json { "id": 300, "organizationId": 1, "customerId": 10, "name": "Bastion Host (Primary)", "hostname": "ssh.example.com", "port": 22, "status": "disabled", "checkInterval": 60, "timeoutSeconds": 30, "notificationEmail": null, "notificationPhoneNumber": null, "lastCheckedAt": "2026-02-26T12:00:00.000Z", "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:01:00.000Z", "config": { "username": "root" }, "sshConfig": { "username": "root" } } ``` ## Errors - `400` SSH monitor ID is required / invalid fields - `401` Unauthorized - `403` Forbidden (readonly users may only update `status`; global supporters cannot update) - `404` Not found ### Notification Channels URL: https://docs.uptimeify.io/api/notification-channels Description: Manage how and where alerts are delivered. Channels can be organization-level (default for all customers), customer-level (override for a specific customer), or website-level (override for a specific monitor). Summary: ## Authentication All examples assume a bearer token: ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Channel Types and Config Each channel type has a specific `config` structure: | Type | Config Fields | Notes | |------|--------------|-------| | `email` | `{ email, to }` | Email address and recipient name | | `sms` | `{ phoneNumber }` | Phone number in international format | | `webhook` | `{ url, method?, headers?, bodyTemplate?, timeout?, retryAttempts?, retryDelay?, expectedStatusCodes?, secret? }` | HTTP webhook. `secret` for HMAC signing | | `slack` | `{ secret }` | Slack incoming webhook URL | | `discord` | `{ secret }` | Discord incoming webhook URL | | `pagerduty` | `{ routingKey }` | PagerDuty Events API v2 routing key | | `pushover` | `{ userKey, apiToken }` | Pushover user key and API token | | `opsgenie` | `{ apiKey }` | Opsgenie API key | Secrets (webhook `secret`, Slack/Discord URLs, PagerDuty routing keys, Pushover credentials, Opsgenie API keys) are **encrypted at rest** and **redacted in API responses** (replaced with `null`, with `hasSecret: true` flags). ## Webhook Signature Verification When a `secret` is configured on a webhook channel, Uptimeify signs outgoing payloads so receivers can verify authenticity. **Algorithm:** HMAC-SHA256 **Header:** `X-Webhook-Signature` — hex-encoded HMAC-SHA256 digest **Companion headers sent with every webhook:** | Header | Value | |--------|-------| | `X-Webhook-Signature` | Hex-encoded HMAC-SHA256 digest | | `X-Webhook-Signature-Algorithm` | `sha256` | | `X-Webhook-Timestamp` | ISO 8601 timestamp (e.g. `2026-05-05T12:00:00.000Z`) | | `X-Webhook-Attempt` | 1-based retry number (e.g. `1`, `2`, `3`) | | `X-Webhook-Event` | Event type: `alert`, `recovery`, or `dnsbl` | **Verification steps:** 1. Read the raw request body as a string (do not parse as JSON first). 2. Compute HMAC-SHA256 using the `secret` you configured in the channel as the key and the raw body string as the message. 3. Compare the result (hex-encoded) with the value of the `X-Webhook-Signature` header using a constant-time comparison. 4. Optionally check `X-Webhook-Timestamp` for replay protection. ```javascript // Node.js verification example const crypto = require('crypto') function verifySignature(rawBody, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex') return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected) ) } ``` ```python # Python verification example def verify_signature(raw_body, signature, secret): expected = hmac.new( secret.encode('utf-8'), raw_body.encode('utf-8'), hashlib.sha256 ).hexdigest() return hmac.compare_digest(signature, expected) ``` ## Scope Resolution When listing channels, the scope determines which channels are returned: - **Organization-level** (`organizationId` only, no `customerId`/`websiteId`): Default channels for all customers - **Customer-level** (`customerId` set, no `websiteId`): Customer-specific overrides - **Website-level** (`websiteId` set): Per-monitor overrides ## Endpoints - [List Notification Channels](./list-notification-channels) - [Create Notification Channel](./create-notification-channel) - [Update Notification Channel](./update-notification-channel) - [Delete Notification Channel](./delete-notification-channel) - [Test Notification Channel](./test-notification-channel) ### Create Notification Channel URL: https://docs.uptimeify.io/api/notification-channels/create-notification-channel Description: Creates a new notification channel. Secrets in config are encrypted server-side. Summary: `POST /api/notification-channels` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `type` | string | Yes | — | Channel type (see full list below) | | `name` | string | Yes | — | Display name | | `config` | object\|string | Yes | — | Channel configuration (see type table). Pass as JSON object or JSON string. | | `organizationId` | number | No | from session | Organization scope | | `customerId` | number | No | null | Customer scope | | `websiteId` | number | No | null | Website scope. Requires `sourceChannelId`. | | `sourceChannelId` | number\|string | Conditional | null | Parent channel ID for website overrides | | `category` | string | No | `direct` | `direct` or `integration` | | `priority` | number | No | 1 | Lower = higher priority | | `delaySeconds` | number | No | 0 | Delay before sending alert | | `conditions` | object\|string | No | null | Alert conditions (e.g., `{"onlyFullService": true, "minIncidentDuration": 300}`) | | `isActive` | boolean | No | true | Whether the channel is active | ## Channel types Direct (`category: "direct"`): `email`, `sms`, `webhook`. Integrations (`category: "integration"`): `slack`, `discord`, `teams`, `pagerduty`, `opsgenie`, `allquiet`, `telegram`, `googlechat`, `mattermost`, `rocketchat`, `matrix`, `lark`, `dingtalk`, `wecom`, `ilert`, `grafanaoncall`, `squadcast`, `incidentio`, `pushover`, `ntfy`, `gotify`, `jira`, `github`, `gitlab`, `linear`, `servicenow`. The `config` fields depend on the type — see [Integrations](/integrations) for what each channel needs. You can validate a channel before saving with the [Test Notification Channel](/api/notification-channels/test-notification-channel) endpoint. ## Example (cURL) — Email channel ```bash curl -X POST "$BASE_URL/api/notification-channels" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "email", "name": "Ops Email", "config": { "email": "ops@example.com", "to": "Ops Team" }, "organizationId": 1 }' ``` ## Example (cURL) — Slack channel ```bash curl -X POST "$BASE_URL/api/notification-channels" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "slack", "name": "Alerts Slack Channel", "config": { "secret": "https://hooks.slack.com/services/T00/B00/xxx" }, "organizationId": 1 }' ``` ## Example (cURL) — Webhook channel ```bash curl -X POST "$BASE_URL/api/notification-channels" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "webhook", "name": "Custom Webhook", "config": { "url": "https://example.com/webhook", "method": "POST", "headers": { "X-Custom-Header": "value" }, "bodyTemplate": "{\"text\": \"{{websiteName}} is {{status}}\"}", "timeout": 30, "retryAttempts": 3, "retryDelay": 60, "expectedStatusCodes": "200,201,204" }, "organizationId": 1 }' ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when creating channels for an organization you cannot write to - `409 Conflict` when a duplicate website-level override already exists ## Response Returns the created notification channel object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Delete Notification Channel URL: https://docs.uptimeify.io/api/notification-channels/delete-notification-channel Description: Deletes a notification channel. If the channel was an org-level default, organization defaults are automatically synced. Summary: `DELETE /api/notification-channels/:id` ## Example (cURL) ```bash curl -X DELETE "$BASE_URL/api/notification-channels/1" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when accessing channels outside your scope - `404 Not found` when the channel does not exist ### List Notification Channels URL: https://docs.uptimeify.io/api/notification-channels/list-notification-channels Description: Returns notification channels scoped by organization, customer, or website. Summary: `GET /api/notification-channels` ## Query Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `organizationId` | number | No | Scope to organization | | `customerId` | number | No | Scope to customer | | `websiteId` | number | No | Scope to website (includes org + customer channels) | ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/notification-channels?organizationId=1" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": 1, "organizationId": 1, "customerId": null, "websiteId": null, "type": "email", "category": "direct", "name": "Ops Email", "config": { "email": "ops@example.com", "to": "Ops Team" }, "priority": 1, "delaySeconds": 0, "conditions": null, "isActive": true, "allowedPackageTypes": null } ] ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when accessing channels outside your scope ### Test Notification Channel URL: https://docs.uptimeify.io/api/notification-channels/test-notification-channel Description: Tests a notification channel configuration. Optionally sends a real test message. Summary: `POST /api/notification-channels/test` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `type` | string | Yes | — | `webhook`, `slack`, `discord`, `pagerduty`, `pushover`, `opsgenie` | | `config` | object | Yes | `{}` | Channel config with secrets | | `organizationId` | number | No | from session | Organization scope | | `customerId` | number | No | null | Customer scope | | `websiteId` | number | No | null | Website scope | | `dryRun` | boolean | No | false | If true, validates only (no actual send) | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/notification-channels/test" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "webhook", "config": { "url": "https://example.com/webhook", "method": "POST", "timeout": 15 }, "dryRun": false }' ``` ## Response ```json { "success": true, "mode": "send", "message": "Webhook delivered successfully", "validation": { "ok": true, "errors": [], "warnings": [] }, "request": { "url": "https://example.com/webhook", "method": "POST", "timeoutSeconds": 15, "headers": {}, "bodyPreview": "...", "bodySize": 256 }, "response": { "reachable": true, "ok": true, "statusCode": 200, "statusText": "OK", "durationMs": 150, "headers": {}, "bodyPreview": null, "bodySize": null } } ``` HTTP 429 responses are treated as "reachable but rate-limited" (success: true). ## Common errors - `401 Unauthorized` when not authenticated - `400 Bad Request` when config is invalid for the given type ### Update Notification Channel URL: https://docs.uptimeify.io/api/notification-channels/update-notification-channel Description: Updates a notification channel. Summary: `PATCH /api/notification-channels/:id` Config is **merged** with existing secrets, preserving encrypted fields that are not provided. ## Request Body (all optional) | Field | Type | Description | |-------|------|-------------| | `type` | string | Channel type | | `name` | string | Display name | | `config` | object\|string | Merged with existing secrets | | `priority` | number | Priority order | | `delaySeconds` | number | Delay before sending | | `conditions` | object\|string\|null | Alert conditions | | `allowedPackageTypes` | string[]\|null | Package types this channel applies to | | `isActive` | boolean | Whether the channel is active | ## Example (cURL) ```bash curl -X PATCH "$BASE_URL/api/notification-channels/1" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Updated Email Channel", "isActive": true }' ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when accessing channels outside your scope - `404 Not found` when the channel does not exist ## Response Returns the updated notification channel object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Organization & Billing URL: https://docs.uptimeify.io/api/organization Description: Path-based organization endpoints use organizationPublicId UUIDs. Summary: ## Endpoints - [Get Organization Details](./get-organization-details) - [Update Organization](./update-organization) - [List Package Configs](./list-package-configs) - [Upsert Package Config](./upsert-package-config) - [Delete Package Config](./delete-package-config) - [Get Billing Details](./get-billing-details) - [Update Billing Details](./update-billing-details) - [List Invoices](./list-invoices) - [Error codes and known API pitfalls](/api/error-codes-and-known-pitfalls) ### Organization SMTP URL: https://docs.uptimeify.io/api/organization-smtp Description: Configure custom SMTP settings so your organization's notification emails are sent through your own mail server. All SMTP endpoints require admin role. Summary: ## Authentication All endpoints accept API bearer tokens or session cookies: ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Endpoints - [Test SMTP Connection](./test-smtp) - [Get SMTP Send Logs](./get-smtp-logs) ### Get SMTP Send Logs URL: https://docs.uptimeify.io/api/organization-smtp/get-smtp-logs Description: Returns recent SMTP send event logs from Redis. Admin-only. Summary: `GET /api/organization/smtp/logs` ## Query Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `limit` | number | 100 | Max events to return (1–500) | ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/organization/smtp/logs?limit=50" \ -H "Cookie: $SESSION_COOKIE" \ -H "Accept: application/json" ``` ## Response ```json { "events": [ { "type": "smtp_send", "timestamp": "2026-04-15T12:00:00.000Z", "to": "admin@example.com", "subject": "Website Down: example.com", "status": "sent" } ] } ``` Returns `{ "events": [] }` if no logs exist or on Redis errors (fails open). ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin ### Test SMTP Connection URL: https://docs.uptimeify.io/api/organization-smtp/test-smtp Description: Tests the SMTP configuration by sending a test email. All parameters are optional — when omitted, stored config values are used. This allows testing new credentials before saving them. Admin-only. Summary: `POST /api/organization/smtp/test` The test also updates the SMTP config's `lastTestedAt`, `lastTestStatus`, and `lastTestError` fields. ## Request Body (all optional) | Field | Type | Description | |-------|------|-------------| | `toEmail` | string | Recipient email address (max 320 chars). Defaults to current user's email. | | `subject` | string | Email subject (1–200 chars). Defaults to `SMTP Test ()`. | | `message` | string | Email body (1–2000 chars). Defaults to a standard test message. | | `host` | string\|null | SMTP server hostname (1–255 chars). Overrides stored config. | | `port` | number\|null | SMTP server port (1–65535). Overrides stored config. | | `username` | string\|null | SMTP username (1–200 chars). Overrides stored config. | | `password` | string\|null | SMTP password (1–500 chars). Overrides stored config (not persisted). | | `tlsMode` | string\|null | `ssl`, `starttls`, or `none`. Overrides stored config. | | `fromName` | string\|null | Sender display name (1–200 chars). Overrides stored config. | | `fromEmail` | string\|null | Sender email address (max 320 chars). Overrides stored config. | | `replyTo` | string\|null | Reply-to email address (max 320 chars). Overrides stored config. | ## Example (cURL) — Using stored config ```bash curl -X POST "$BASE_URL/api/organization/smtp/test" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{}' ``` ## Example (cURL) — Testing new credentials ```bash curl -X POST "$BASE_URL/api/organization/smtp/test" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "host": "smtp.example.com", "port": 587, "tlsMode": "starttls", "username": "alerts@example.com", "password": "secret-password", "fromName": "Uptimeify Alerts", "fromEmail": "alerts@example.com", "toEmail": "admin@example.com" }' ``` ## Response (success) ```json { "success": true, "messageId": "" } ``` ## Common errors - `400 Missing recipient email (toEmail)` when no recipient and user has no email - `400 SMTP config incomplete (host/port required)` when host or port is missing - `400 SMTP config incomplete (username required)` when username is needed but missing - `400 SMTP password missing (username is set)` when password is needed but missing - `400 SMTP config incomplete (fromEmail required)` when fromEmail is missing - `403 Forbidden` when not an admin - `502 Failed to send SMTP test email` when the SMTP connection fails ### Delete Package Config URL: https://docs.uptimeify.io/api/organization/delete-package-config Description: Deletes a package config for an organization. Deletion is only allowed if no customers currently use the given :packageType. The package is resolved directly from the path parameter, so values like test1 work as long as they match the stored packageType. Summary: `DELETE /api/package-configs/:packageType` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE "$BASE_URL/api/package-configs/pro" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` Notes: - The organization is derived automatically from your authenticated session or API token. - The legacy route `DELETE /api/organizations/:organizationPublicId/package-configs/:packageType` remains supported for compatibility. - The plural org-less alias `DELETE /api/organizations/package-configs/:packageType` is also supported. - Global admins need an active organization context in the authenticated session for the org-less route. ## Response ```json { "success": true } ``` ## Common errors - `404 Package not found` when the config does not exist - `409 Package is still in use by customers` when customers are assigned this package type - `400 Package type is required` when `:packageType` is missing - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization Authorization note: - Write access is required (organization admin or global admin). ### Get Billing Details URL: https://docs.uptimeify.io/api/organization/get-billing-details Description: Returns billing information and payment methods for the organization in your authenticated session. Summary: `GET /api/organization/billing` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/organization/billing" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` Notes: - The organization is derived automatically from your authenticated session or API token. - The legacy route `GET /api/organizations/:organizationPublicId/billing` remains supported for compatibility. - The plural org-less alias `GET /api/organizations/billing` is also supported. - Global admins need an active organization context in the authenticated session for the org-less route. ## Response ```json { "billingEmail": "billing@example.com", "paymentMethod": "mollie" } ``` ## Common errors - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Get Organization Details URL: https://docs.uptimeify.io/api/organization/get-organization-details Description: Returns details of the organization from your authenticated session. Summary: `GET /api/organization` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/organization" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` Notes: - The organization is derived automatically from your authenticated session or API token. - The legacy route `GET /api/organizations/:organizationPublicId` remains supported for compatibility. - The plural org-less alias `GET /api/organizations` is also supported. - Global admins need an active organization context in the authenticated session for the org-less route. ## Response ```json { "id": 1, "name": "My Org", "companyName": "My Company GmbH", "street": "Sample St. 1", "postalCode": "12345", "city": "Berlin", "country": "DE", "vatId": "DE123456789", "billingEmail": "billing@example.com", "createdAt": "2023-01-01T00:00:00.000Z" } ``` ## Common errors - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### List Invoices URL: https://docs.uptimeify.io/api/organization/list-invoices Description: Lists all invoices for the organization (Mollie). Summary: `GET /api/mollie/invoices` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/mollie/invoices" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` Notes: - The organization is derived automatically from your authenticated session or API token. - The legacy route `GET /api/organizations/:organizationPublicId/mollie/invoices` remains supported for compatibility. - The `pdfUrl` values in the response use the org-less download route `/api/invoices/:invoiceId/pdf`. - Global admins need an active organization context in the authenticated session for the org-less route. ## Response ```json { "invoices": [ { "id": "inv_123456", "reference": "INV-2024-001", "status": "paid", "issuedAt": "2024-01-15T10:00:00.000Z", "netAmount": { "value": "29.99", "currency": "EUR" }, "pdfUrl": "/api/invoices/inv_123456/pdf" }, { "id": "inv_123455", "reference": "INV-2023-128", "status": "paid", "issuedAt": "2023-12-15T10:00:00.000Z", "netAmount": { "value": "29.99", "currency": "EUR" }, "pdfUrl": "/api/invoices/inv_123455/pdf" } ] } ``` ## Common errors - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Not authorized` when you cannot access the organization ### List Package Configs URL: https://docs.uptimeify.io/api/organization/list-package-configs Description: Returns all package configurations for the organization in your authenticated session. Each config also includes a usedByCustomerCount field. Summary: `GET /api/package-configs` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/package-configs" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` Notes: - The organization is derived automatically from your authenticated session or API token. - The legacy route `GET /api/organizations/:organizationPublicId/package-configs` remains supported for compatibility. - Global admins need an active organization context in the authenticated session for the org-less route. ## Response ```json [ { "id": 10, "packageType": "pro", "maxUrls": 100, "dataRetentionMonths": 12, "checkIntervalMinutes": 1, "checkLocations": 3, "notificationDelayMinutes": 0, "reminderDelayMinutes": 10, "alertConsecutiveChecks": 3, "alertLocationThreshold": "majority", "alertLocationThresholdCount": 2, "alertReminderInterval": 60, "enableSslCheck": true, "enableHttpsCheck": true, "enableStatusCheck": true, "enableSizeCheck": true, "enableResponseTimeCheck": true, "enableKeywordCheck": false, "enableEmailAlerts": true, "enableSmsAlerts": true, "enableWebhookAlerts": true, "enableIntegrationAlerts": true, "enablePostRequestEscalation": false, "enableMaintenanceWindows": true, "enablePdfReports": true, "notes": null, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z", "usedByCustomerCount": 4 } ] ``` ## Common errors - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Create Report URL: https://docs.uptimeify.io/api/organization/reports/create-report Description: Creates an organization-level report configuration. Requires a plan that includes organization reports and available report quota. Summary: `POST /api/organization/reports` Creates a recurring organization report. The organization is derived from your authenticated session or API token. Requires organization **admin** (API tokens act as organization admins). Read-only users cannot create reports. ## Request Body | Field | Type | Required | Notes | |---|---|---|---| | `name` | string | yes | 1–200 chars. | | `enabled` | boolean | no | Default `true`. | | `frequency` | `"daily" \| "weekly" \| "monthly"` | no | Default `monthly`. | | `weekday` | integer 0–6 | when `weekly` | 0 = Sunday. | | `dayOfMonth` | integer 1–28 | when `monthly` | Capped at 28. | | `sendHour` | integer 0–23 | no | Default `2`, in `timezone`. | | `timezone` | string | no | IANA tz, default `Europe/Berlin`. | | `scopeMode` | `"all" \| "customers" \| "tags"` | no | Default `all`. | | `scopeCustomerIds` | integer[] | when `customers` | Must belong to your organization. | | `scopeTagIds` | integer[] | when `tags` | Must belong to your organization. | | `inclusionMode` | `"all" \| "problems" \| "threshold"` | no | Default `all`. | | `problemSignals` | object | no | `{ incident, downtimeMinutes, sslDaysLt, responseBreach }`. | | `thresholdUptimeLt` | number | when `threshold` | e.g. `99.9`. | | `thresholdResponseGt` | integer (ms) | when `threshold` | | | `sendWhenEmpty` | boolean | no | Send an "all clear" report when no site matches. Default `false`. | | `sections` | object | no | Six booleans toggling report sections. | | `format` | `"email" \| "email_pdf"` | no | Default `email_pdf`. | | `recipientEmails` | string[] | no | Agency-side email recipients (max 50). | | `recipientUserIds` | string[] | no | Organization team member user ids (max 50). | ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST "$BASE_URL/api/organization/reports" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Weekly Ops Digest", "frequency": "weekly", "weekday": 1, "scopeMode": "all", "inclusionMode": "problems", "problemSignals": { "incident": true, "downtimeMinutes": 5, "sslDaysLt": 14, "responseBreach": true }, "format": "email_pdf", "recipientEmails": ["ops@agency.io"] }' ``` ## Response ```json { "id": "3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90", "name": "Weekly Ops Digest", "enabled": true, "frequency": "weekly", "weekday": 1, "dayOfMonth": null, "sendHour": 2, "timezone": "Europe/Berlin", "scopeMode": "all", "inclusionMode": "problems", "format": "email_pdf", "recipientEmails": ["ops@agency.io"], "recipientUserIds": [] } ``` ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — not an organization admin. - `400` (`invalidReportSchedule`) — `weekly` without `weekday`, or `monthly` without `dayOfMonth`. - `400` (`invalidReportScope`) — scope ids are not owned by your organization, or `threshold` mode without a threshold. ### Delete Report URL: https://docs.uptimeify.io/api/organization/reports/delete-report Description: Permanently deletes an organization report configuration and its scheduling. Past report runs are not deleted. Summary: `DELETE /api/organization/reports/:id` Deletes a report configuration. `:id` is the report's `id` (a UUID). The organization is derived from your authenticated session or API token, and the report must belong to it. Requires organization **admin** (API tokens act as organization admins). Read-only users cannot delete reports. This stops future scheduled runs of the report. Historical [report runs](/api/organization/reports/list-report-runs) already generated for this report are not affected and remain retrievable. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" REPORT_ID="3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90" curl -X DELETE "$BASE_URL/api/organization/reports/$REPORT_ID" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "success": true } ``` ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — not an organization admin. - `404 Not Found` (`notFound`) — no report with this id exists for your organization. ### Download Report PDF URL: https://docs.uptimeify.io/api/organization/reports/download-report-pdf Description: Redirects to a short-lived signed URL for the archived PDF of a report run. Summary: `GET /api/organization/report-runs/:id/pdf` Redirects (`302`) to a time-limited, signed object-storage URL for the PDF archived for a report run. `:id` is the run's `id` (a UUID), as returned by [List Report Runs](/api/organization/reports/list-report-runs). The run must belong to your organization. Available to any organization role, including **read-only** users. Only runs with `format: "email_pdf"` that completed successfully archive a PDF — check `hasPdf` on the run before calling this endpoint. `format: "email"` runs, and runs that failed or were skipped, have no PDF and return `404`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" RUN_ID="9a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d" curl -X GET "$BASE_URL/api/organization/report-runs/$RUN_ID/pdf" \ -H "Authorization: Bearer $TOKEN" \ -L -o report.pdf ``` ## Response `302 Found` with a `Location` header pointing at a signed, short-lived URL for the PDF object. No response body. Follow the redirect (`-L` in cURL, or your HTTP client's default redirect handling) to download the file. ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — you do not have access to this organization. - `404 Not Found` (`reportRunNotFound`) — no run with this id exists for your organization. - `404 Not Found` (`reportRunNoPdf`) — the run has no archived PDF (it was an email-only report, or generation failed/was skipped). ### Get Report URL: https://docs.uptimeify.io/api/organization/reports/get-report Description: Returns a single organization report configuration by its public id. Summary: `GET /api/organization/reports/:id` Returns one report configuration. `:id` is the report's `id` (a UUID), as returned by [Create Report](/api/organization/reports/create-report) or [List Reports](/api/organization/reports/list-reports). The report must belong to your organization. Available to any organization role, including **read-only** users. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" REPORT_ID="3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90" curl -X GET "$BASE_URL/api/organization/reports/$REPORT_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "id": "3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90", "name": "Weekly Ops Digest", "enabled": true, "frequency": "weekly", "weekday": 1, "dayOfMonth": null, "sendHour": 2, "timezone": "Europe/Berlin", "scopeMode": "all", "scopeCustomerIds": [], "scopeTagIds": [], "inclusionMode": "problems", "problemSignals": { "incident": true, "downtimeMinutes": 5, "sslDaysLt": 14, "responseBreach": true }, "thresholdUptimeLt": null, "thresholdResponseGt": null, "sendWhenEmpty": false, "sections": { "fleetSummary": true, "worstPerformers": true, "perSiteTable": true, "incidentLog": true, "sslExpiry": true, "groupByCustomer": false }, "format": "email_pdf", "recipientEmails": ["ops@agency.io"], "recipientUserIds": [], "createdAt": "2026-06-01T02:00:00.000Z", "updatedAt": "2026-06-01T02:00:00.000Z" } ``` ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — you do not have access to this organization. - `404 Not Found` (`notFound`) — no report with this id exists for your organization. ### List Report Runs URL: https://docs.uptimeify.io/api/organization/reports/list-report-runs Description: Returns the organization's report generation/delivery history, optionally filtered to a single report. Summary: `GET /api/organization/report-runs` Lists report runs for the organization, newest first. A run is created every time a report is generated — on schedule or via [Send Report Now](/api/organization/reports/send-report-now). The organization is derived from your authenticated session or API token. Available to any organization role, including **read-only** users. ## Query Parameters | Field | Type | Required | Notes | |---|---|---|---| | `reportId` | string (uuid) | no | Restrict to runs of one report. If the id does not resolve to a report in your organization, returns `[]`. | | `limit` | integer | no | Default `50`, capped at `200`. | | `offset` | integer | no | Default `0`. | ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/organization/report-runs?reportId=3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90&limit=20" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": "9a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "reportId": "3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90", "reportName": "Weekly Ops Digest", "periodStart": "2026-05-25T00:00:00.000Z", "periodEnd": "2026-06-01T00:00:00.000Z", "periodLabel": "May 25 – Jun 1, 2026", "status": "sent", "trigger": "schedule", "sentAt": "2026-06-01T02:00:12.000Z", "recipients": ["ops@agency.io"], "hasPdf": true, "summary": { "sitesIncluded": 42, "incidents": 3 }, "createdAt": "2026-06-01T02:00:00.000Z" } ] ``` `status` is one of `pending`, `generating`, `sent`, `failed`, `skipped_empty`. `trigger` is `schedule` or `manual`. `hasPdf` is `true` only when a PDF was archived for this run — use it to decide whether to call [Download Report PDF](/api/organization/reports/download-report-pdf). ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — you do not have access to this organization. ### List Reports URL: https://docs.uptimeify.io/api/organization/reports/list-reports Description: Returns all organization report configurations plus the organization's report entitlement (plan feature flag and quota). Summary: `GET /api/organization/reports` Lists the organization's recurring report configurations, newest first. The organization is derived from your authenticated session or API token. Available to any organization role, including **read-only** users. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/organization/reports" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "entitlement": { "enabled": true, "limit": 10 }, "reports": [ { "id": "3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90", "name": "Weekly Ops Digest", "enabled": true, "frequency": "weekly", "weekday": 1, "dayOfMonth": null, "sendHour": 2, "timezone": "Europe/Berlin", "scopeMode": "all", "scopeCustomerIds": [], "scopeTagIds": [], "inclusionMode": "problems", "problemSignals": { "incident": true, "downtimeMinutes": 5, "sslDaysLt": 14, "responseBreach": true }, "thresholdUptimeLt": null, "thresholdResponseGt": null, "sendWhenEmpty": false, "sections": { "fleetSummary": true, "worstPerformers": true, "perSiteTable": true, "incidentLog": true, "sslExpiry": true, "groupByCustomer": false }, "format": "email_pdf", "recipientEmails": ["ops@agency.io"], "recipientUserIds": [], "createdAt": "2026-06-01T02:00:00.000Z", "updatedAt": "2026-06-01T02:00:00.000Z" } ] } ``` `entitlement.enabled` reflects whether the organization's plan includes organization reports; `entitlement.limit` is the maximum number of report configurations allowed. Both are derived from the organization's active pricing/custom-pricing rows, independent of how many reports currently exist. ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — you do not have access to this organization. ### Send Report Now URL: https://docs.uptimeify.io/api/organization/reports/send-report-now Description: Queues an immediate, out-of-schedule generation and delivery of an organization report. Summary: `POST /api/organization/reports/:id/send-now` Enqueues a manual run of a report configuration, independent of its `frequency`/`sendHour` schedule. `:id` is the report's `id` (a UUID). The organization is derived from your authenticated session or API token, and the report must belong to it. Requires organization **admin** (API tokens act as organization admins). Read-only users cannot trigger sends. This endpoint only queues the job — it does not wait for generation or delivery to complete. Poll [List Report Runs](/api/organization/reports/list-report-runs) (filtered by `reportId`) to see the resulting run once its `status` moves past `pending`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" REPORT_ID="3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90" curl -X POST "$BASE_URL/api/organization/reports/$REPORT_ID/send-now" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "queued": true, "jobId": "orgreport-manual-3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90-1b6e..." } ``` ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — not an organization admin. - `404 Not Found` (`notFound`) — no report with this id exists for your organization. ### Update Report URL: https://docs.uptimeify.io/api/organization/reports/update-report Description: Updates an organization report configuration. All fields are optional; at least one must be provided. Summary: `PATCH /api/organization/reports/:id` Partially updates a report configuration. `:id` is the report's `id` (a UUID). The organization is derived from your authenticated session or API token, and the report must belong to it. Requires organization **admin** (API tokens act as organization admins). Read-only users cannot update reports. Only send the fields you want to change. Cross-field validation (schedule and scope) is re-run against the **merged** result — a `PATCH` that only changes `frequency` to `weekly` without also sending `weekday` fails if the existing report has no `weekday` set. ## Request Body Same fields as [Create Report](/api/organization/reports/create-report), all optional — but at least one field must be present: | Field | Type | Notes | |---|---|---| | `name` | string | 1–200 chars. | | `enabled` | boolean | | | `frequency` | `"daily" \| "weekly" \| "monthly"` | | | `weekday` | integer 0–6 \| null | Required (effectively) when the resulting `frequency` is `weekly`. | | `dayOfMonth` | integer 1–28 \| null | Required (effectively) when the resulting `frequency` is `monthly`. | | `sendHour` | integer 0–23 | | | `timezone` | string | IANA tz. | | `scopeMode` | `"all" \| "customers" \| "tags"` | | | `scopeCustomerIds` | integer[] | Must belong to your organization. | | `scopeTagIds` | integer[] | Must belong to your organization. | | `inclusionMode` | `"all" \| "problems" \| "threshold"` | | | `problemSignals` | object | `{ incident, downtimeMinutes, sslDaysLt, responseBreach }`. | | `thresholdUptimeLt` | number \| null | | | `thresholdResponseGt` | integer (ms) \| null | | | `sendWhenEmpty` | boolean | | | `sections` | object | Six booleans toggling report sections. | | `format` | `"email" \| "email_pdf"` | | | `recipientEmails` | string[] | Max 50. | | `recipientUserIds` | string[] | Max 50. | ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" REPORT_ID="3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90" curl -X PATCH "$BASE_URL/api/organization/reports/$REPORT_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "enabled": false, "recipientEmails": ["ops@agency.io", "cs@agency.io"] }' ``` ## Response ```json { "id": "3f1c9c1e-8d2a-4c7e-9b1a-2d5f6a7b8c90", "name": "Weekly Ops Digest", "enabled": false, "frequency": "weekly", "weekday": 1, "dayOfMonth": null, "sendHour": 2, "timezone": "Europe/Berlin", "scopeMode": "all", "inclusionMode": "problems", "format": "email_pdf", "recipientEmails": ["ops@agency.io", "cs@agency.io"], "recipientUserIds": [] } ``` ## Common errors - `401 Unauthorized` — not authenticated. - `403 Forbidden` (`forbidden`) — not an organization admin. - `404 Not Found` (`notFound`) — no report with this id exists for your organization. - `400` (`invalidReportSchedule`) — the resulting `weekly` config has no `weekday`, or the resulting `monthly` config has no `dayOfMonth`. - `400` (`invalidReportScope`) — scope ids are not owned by your organization, or the resulting `threshold` mode has no threshold. ### Update Billing Details URL: https://docs.uptimeify.io/api/organization/update-billing-details Description: Updates billing information for the organization in your authenticated session. Summary: `PATCH /api/organization/billing` ## Request Body ```json { "billingEmail": "billing@example.com" } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/organization/billing" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "billingEmail": "billing@example.com" }' ``` ## Notes - `billingEmail` is currently the only supported field for this endpoint. - The organization is derived automatically from your authenticated session or API token. - The legacy route `PATCH /api/organizations/:organizationPublicId/billing` remains supported for compatibility. - The plural org-less alias `PATCH /api/organizations/billing` is also supported. - Global admins need an active organization context in the authenticated session for the org-less route. ## Common errors - `400 Invalid request body` when the payload does not match the schema - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you do not have admin access to update billing settings ## Response Returns the updated organization billing details. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Update Organization URL: https://docs.uptimeify.io/api/organization/update-organization Description: Updates the organization from your authenticated session. Summary: `PATCH /api/organization` ## Request Body ```json { "name": "New Name", "companyName": "New Company Name", "street": "New Street", "postalCode": "54321", "city": "New City", "country": "US", "vatId": "US123", "billingEmail": "new@example.com", "defaultNotificationChannels": { "email": true, "sms": false, "webhook": true, "integrations": false }, "defaultNotificationTargets": { "email": "both", // customer, organization, both "sms": "organization", "webhook": "organization", "integrations": "customer" } } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/organization" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "name": "New Name", "billingEmail": "new@example.com" }' ``` Notes: - The organization is derived automatically from your authenticated session or API token. - The legacy route `PATCH /api/organizations/:organizationPublicId` remains supported for compatibility. - The plural org-less alias `PATCH /api/organizations` is also supported. - Global admins need an active organization context in the authenticated session for the org-less route. ## Common errors - `400 Invalid request body` when the payload does not match the schema - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you do not have admin access to update the organization ## Response Returns the updated organization object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Upsert Package Config URL: https://docs.uptimeify.io/api/organization/upsert-package-config Description: Creates a new package config (by :packageType) or updates an existing one. packageType is a free-form identifier chosen by the organization, and customer endpoints can later reference that same key. Summary: `PATCH /api/package-configs/:packageType` This endpoint is the source of truth for alerting-related defaults like `alertConsecutiveChecks` and feature flags like `enableEmailAlerts`. ## Request Body All fields are optional and can be updated over time. If you want a human-friendly package label in the UI, set `displayName` in addition to the technical `packageType` key. ```json { "displayName": "Pro Care", "maxUrls": 100, "dataRetentionMonths": 12, "checkIntervalMinutes": 1, "checkLocations": 3, "notificationDelayMinutes": 0, "reminderDelayMinutes": 10, "alertConsecutiveChecks": 3, "alertLocationThreshold": "majority", "alertLocationThresholdCount": 2, "alertReminderInterval": 60, "enableEmailAlerts": true, "enableSmsAlerts": true, "enableWebhookAlerts": true, "enableIntegrationAlerts": true, "enablePostRequestEscalation": false, "enableMaintenanceWindows": true, "enablePdfReports": true, "allowSelfService": true, "maxSelfServiceUrls": 10, "notes": "Default for PRO customers" } ``` ### Monitor ownership defaults `allowSelfService` (default `false`) and `maxSelfServiceUrls` (default `0`) are the package-tier defaults for the [managed vs. self-service](/monitoring/managed-vs-self-service) model. Every customer on the package inherits them unless the customer carries its own non-`null` override (see [Update Customer](/api/customers/update-customer)). `maxSelfServiceUrls` caps a customer's **total** self-service monitors across all monitor types. The `enable*` alert flags double as the inherited channel-type policy for the same model. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/package-configs/pro" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "displayName":"Pro Care", "maxUrls":100, "dataRetentionMonths":12, "checkIntervalMinutes":1, "checkLocations":3, "notificationDelayMinutes":0, "reminderDelayMinutes":10, "alertConsecutiveChecks":3, "alertLocationThreshold":"majority", "alertLocationThresholdCount":2, "alertReminderInterval":60, "enableEmailAlerts":true, "enableSmsAlerts":true, "enableWebhookAlerts":true, "enableIntegrationAlerts":true, "enableMaintenanceWindows":true, "enablePdfReports":true, "notes":"Default for PRO customers" }' ``` ## Response Returns the created/updated package config. ```json { "id": 10, "packageType": "pro", "displayName": "Pro Care", "maxUrls": 100, "dataRetentionMonths": 12, "checkIntervalMinutes": 1, "checkLocations": 3, "notificationDelayMinutes": 0, "reminderDelayMinutes": 10, "alertConsecutiveChecks": 3, "alertLocationThreshold": "majority", "alertLocationThresholdCount": 2, "alertReminderInterval": 60, "enableEmailAlerts": true, "enableSmsAlerts": true, "enableWebhookAlerts": true, "enableIntegrationAlerts": true, "enableMaintenanceWindows": true, "enablePdfReports": true, "notes": "Default for PRO customers", "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z" } ``` Notes: - The organization is derived automatically from your authenticated session or API token. - The body-based variant `PATCH /api/package-configs` is also supported when `packageType` is sent in the request body. - The legacy route `PATCH /api/organizations/:organizationPublicId/package-configs/:packageType` remains supported for compatibility. - The plural org-less alias `PATCH /api/organizations/package-configs/:packageType` is also supported. - Global admins need an active organization context in the authenticated session for the org-less route. ## Common errors - `400 Package type is required` when `:packageType` is missing - `400 Organization ID is required in the authenticated session` when no organization can be derived from the current session/token - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization Authorization note: - Write access is required (organization admin or global admin). ### Status Pages URL: https://docs.uptimeify.io/api/status-pages Description: Create and manage public status pages that display the operational status of your monitored websites, recent incidents, and maintenance windows. Summary: Status pages can be public (accessible by anyone) or restricted to customer members. Custom domains are supported with DNS verification. ## Authentication All examples assume a bearer token: ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Endpoints - [List Status Pages](./list-status-pages) - [Create Status Page](./create-status-page) - [Update Status Page](./update-status-page) - [Delete Status Page](./delete-status-page) - [Get Public Status Page](./get-public-status-page) - [Get Status Page Design](./get-status-page-design) - [Update Status Page Design](./update-status-page-design) - [Add Custom Domain](./add-status-page-domain) - [Remove Custom Domain](./remove-status-page-domain) - [Verify Status Page Domain](./verify-status-page-domain) - [Activate Status Page Domain](./activate-status-page-domain) ### Activate Status Page Domain URL: https://docs.uptimeify.io/api/status-pages/activate-status-page-domain Description: Activates a verified custom domain for a status page. Admin-only. Summary: `POST /api/status-pages/domains/activate` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `domainId` | number | Yes | — | The verified domain ID to activate | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/status-pages/domains/activate" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "domainId": 42 }' ``` ## Response ```json { "activated": true, "domain": { "id": 42, "hostname": "status.example.com", "status": "active", "role": "status_page", "isPrimary": false, "verificationToken": "abc123-def456-ghi789", "verifiedAt": "2026-05-01T12:00:00.000Z", "createdAt": "2026-05-01T11:00:00.000Z", "updatedAt": "2026-05-01T12:30:00.000Z" } } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `400 Bad Request` when the domain is not yet verified ### Add Custom Domain to Status Page URL: https://docs.uptimeify.io/api/status-pages/add-status-page-domain Description: Adds a custom hostname to an existing status page and returns the DNS TXT record needed for verification. Admin-only. Summary: `POST /api/status-pages/domains` ## Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `statusPageId` | number \| string | Yes | The status page ID or publicId | | `hostname` | string | Yes | The custom hostname (e.g. `status.example.com`) | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/status-pages/domains" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "statusPageId": 1, "hostname": "status.example.com" }' ``` ## Response ```json { "domain": { "id": 42, "hostname": "status.example.com", "status": "pending", "role": "status_page", "verificationToken": "abc123-def456-ghi789", "verifiedAt": null, "createdAt": "2026-05-01T11:00:00.000Z", "updatedAt": "2026-05-01T11:00:00.000Z" }, "dns": { "txtName": "_uptimeify-verify.status.example.com", "txtValue": "abc123-def456-ghi789" } } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `404 Not found` when the status page does not exist - `409 Conflict` when the hostname is already in use - `422 Unprocessable Entity` when the hostname is reserved or invalid ### Create Status Page URL: https://docs.uptimeify.io/api/status-pages/create-status-page Description: Creates a new status page. Requires admin role. Summary: `POST /api/status-pages` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `customerId` | number | Yes | — | Customer ID (must belong to your organization) | | `name` | string | Yes | — | Display name (1–120 chars). Slug auto-generated from name. | | `slug` | string | No | auto | URL slug (1–120 chars, auto-normalized to lowercase-hyphens) | | `description` | string | No | null | Description (max 1000 chars) | | `visibility` | string | No | `public` | `public` or `customer_members_only` | | `isPublished` | boolean | No | true | Whether the page is publicly visible | | `customDomainHostname` | string | No | null | Custom domain (3–253 chars). Creates a pending DNS verification record. | | `hiddenMonitors` | array | No | `[]` | Monitors to hide from this status page. Each entry is `{ "type": "http"\|"dns"\|"icmp"\|"smtp"\|"ssh"\|"ftp"\|"imap_pop", "id": }`. Omit or send `[]` to show all monitors (the default). Monitors added later appear automatically. Maximum 500 entries. | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/status-pages" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customerId": 5, "name": "Production Status", "description": "Real-time status of our production services", "visibility": "public", "hiddenMonitors": [{ "type": "http", "id": 42 }] }' ``` ## Response ```json { "statusPage": { "id": 1, "publicId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "organizationId": 1, "customerId": 5, "name": "Production Status", "slug": "production-status", "description": "Real-time status of our production services", "visibility": "public", "isPublished": true, "showRecentIncidents": false, "showRecentMaintenance": false, "customDomainId": null, "createdAt": "2026-01-15T10:00:00.000Z", "updatedAt": "2026-01-15T10:00:00.000Z" }, "dns": null } ``` If `customDomainHostname` is provided, the response includes DNS verification instructions: ```json { "dns": { "txtName": "_uptimeify-verify.status.example.com", "txtValue": "abc123-def456-ghi789" } } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `409 Conflict` when slug is already taken ### Delete Status Page URL: https://docs.uptimeify.io/api/status-pages/delete-status-page Description: Permanently deletes a status page. Requires admin role. Summary: `DELETE /api/status-pages/:id` ## Example (cURL) ```bash curl -X DELETE "$BASE_URL/api/status-pages/1" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "deleted": true, "id": 1 } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `404 Not found` when the status page does not exist ### Get Public Status Page URL: https://docs.uptimeify.io/api/status-pages/get-public-status-page Description: Two endpoints serve the public status page view: Summary: - `GET /api/status-pages/public/:slug` — lookup by URL slug - `GET /api/status-pages/public/by-id/:id` — lookup by numeric ID No authentication required for `visibility: public` pages. Customer-member authentication required for `visibility: customer_members_only` pages. ## Response ```json { "statusPage": { "id": 1, "organizationId": 1, "customerId": 5, "name": "Production Status", "slug": "production-status", "description": "Real-time status of our production services", "visibility": "public", "isPublished": true, "showRecentIncidents": true, "showRecentMaintenance": true, "overallState": "operational", "createdAt": "2026-01-15T10:00:00.000Z", "updatedAt": "2026-01-15T10:00:00.000Z" }, "websites": [ { "id": 101, "name": "Main Site", "url": "https://example.com", "status": "active", "state": "operational", "inMaintenance": false, "openIncidents": 0, "lastCheckedAt": "2026-05-01T12:00:00.000Z" } ], "maintenanceHistory": [], "incidentHistory": [] } ``` `state` values: `operational`, `warning` (SSL-only incidents), `degraded` (non-SSL incidents), `maintenance` (active maintenance window). `overallState` is the most severe state across all websites. ## Common errors - `404 Not found` when the status page does not exist or is not published - `403 Forbidden` for `customer_members_only` pages when the user is not a member ### Get Status Page Design URL: https://docs.uptimeify.io/api/status-pages/get-status-page-design Description: Returns the current visual design configuration for a status page. Requires admin role. Summary: `GET /api/status-pages/:id/design` ## Path Parameter | Parameter | Description | |-----------|-------------| | `id` | Status page ID or `publicId` (UUID) | ## Example (cURL) ```bash curl "$BASE_URL/api/status-pages/db58058e-4b58-4d97-a314-3bb8e279a182/design" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "designConfig": { "layout": "timeline", "colorScheme": "dark", "accentColor": "#f59e0b", "headerStyle": "simple", "fontFamily": "system", "cardRadius": "md", "pageWidth": "lg", "customTitle": "", "customSubtitle": "", "showPoweredBy": true, "showUptimeStats": true, "showServiceUrls": false, "showLastChecked": false, "showHistory": true } } ``` If no design has been saved yet all fields reflect the defaults. ## Common errors - `401 Unauthorized` — not authenticated - `403 Forbidden` — not an admin - `404 Not found` — status page does not exist ### List Status Pages URL: https://docs.uptimeify.io/api/status-pages/list-status-pages Description: Returns all status pages for the organization. Each page includes its custom domain info if configured. Summary: `GET /api/status-pages` ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/status-pages" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "statusPages": [ { "id": 1, "publicId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "organizationId": 1, "customerId": 5, "customerPublicId": "f7e6d5c4-b3a2-1098-7654-321fedcba098", "name": "Production Status", "slug": "production-status", "description": "Real-time status of our production services", "visibility": "public", "isPublished": true, "showRecentIncidents": true, "showRecentMaintenance": true, "customDomainId": null, "createdAt": "2026-01-15T10:00:00.000Z", "updatedAt": "2026-01-15T10:00:00.000Z" } ] } ``` ## Common errors - `401 Unauthorized` when not authenticated ### Remove Custom Domain from Status Page URL: https://docs.uptimeify.io/api/status-pages/remove-status-page-domain Description: Removes a custom domain from a status page. Deletes the domain record; the status page's customDomainId is automatically set to null. Admin-only. Summary: `DELETE /api/status-pages/domains/:id` ## Path Parameters | Parameter | Type | Description | |-----------|------|-------------| | `id` | number | The domain ID to remove | ## Example (cURL) ```bash curl -X DELETE "$BASE_URL/api/status-pages/domains/42" \ -H "Authorization: Bearer $TOKEN" ``` ## Response `204 No Content` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `404 Not found` when the domain does not exist - `422 Unprocessable Entity` when the domain ID is invalid ### Update Status Page URL: https://docs.uptimeify.io/api/status-pages/update-status-page Description: Updates a status page. At least one field must be provided. Requires admin role. Summary: `PATCH /api/status-pages/:id` ## Request Body (all optional) | Field | Type | Description | |-------|------|-------------| | `customerId` | number | Move status page to another customer | | `name` | string | Display name (1–120 chars) | | `slug` | string | URL slug (1–120 chars, 409 on conflict) | | `description` | string\|null | Description (max 1000 chars). `null` clears it. | | `visibility` | string | `public` or `customer_members_only` | | `isPublished` | boolean | Publish or unpublish the page | | `showRecentIncidents` | boolean | Show recent incidents section | | `showRecentMaintenance` | boolean | Show recent maintenance section | | `designConfig` | object | Visual design settings (layout, colors, typography, …). See [Update Status Page Design](./update-status-page-design) for all fields. | | `hiddenMonitors` | array | Monitors to hide from this status page. Each entry is `{ "type": "http"\|"dns"\|"icmp"\|"smtp"\|"ssh"\|"ftp"\|"imap_pop", "id": }`. Omit or send `[]` to show all monitors (the default). Monitors added later appear automatically. Maximum 500 entries. | When present, `hiddenMonitors` replaces the stored list in full; omit the field to leave it unchanged; send `[]` to show all monitors again. ## Example (cURL) ```bash curl -X PATCH "$BASE_URL/api/status-pages/1" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Production Status - Updated", "isPublished": true, "showRecentIncidents": true, "hiddenMonitors": [{ "type": "http", "id": 42 }] }' ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `404 Not found` when the status page does not exist - `409 Conflict` when slug is already taken ## Response Returns the updated status page object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Update Status Page Design URL: https://docs.uptimeify.io/api/status-pages/update-status-page-design Description: Updates the visual design configuration of a status page. Only the fields you provide are changed — all other settings keep their current values. Requires admin role. Summary: `PATCH /api/status-pages/:id/design` ## Path Parameter | Parameter | Description | |-----------|-------------| | `id` | Status page ID or `publicId` (UUID) | ## Request Body (all optional) ### Layout | Field | Type | Values | Default | Description | |-------|------|--------|---------|-------------| | `layout` | string | `classic` `cards` `minimal` `sleek` `board` `split` `timeline` `compact` | `classic` | Visual layout template | | `pageWidth` | string | `sm` `md` `lg` `xl` | `lg` | Max content width: sm = 672 px, md = 896 px, lg = 1024 px, xl = 1280 px | ### Colors | Field | Type | Values | Default | Description | |-------|------|--------|---------|-------------| | `colorScheme` | string | `light` `dark` `auto` | `auto` | Color mode. `auto` follows the visitor's system preference. | | `accentColor` | string | hex, e.g. `#6366f1` | `#6366f1` | Brand accent color used for highlights, borders, and gradients | ### Typography & Style | Field | Type | Values | Default | Description | |-------|------|--------|---------|-------------| | `fontFamily` | string | `system` `mono` | `system` | `system` = default sans-serif, `mono` = monospace | | `cardRadius` | string | `none` `md` `xl` | `md` | Card corner radius: none = sharp, md = rounded, xl = pill | ### Header | Field | Type | Values | Default | Description | |-------|------|--------|---------|-------------| | `headerStyle` | string | `simple` `centered` `hero` | `simple` | `simple` = left-aligned, `centered` = centered, `hero` = full gradient banner | | `customTitle` | string | max 120 chars | `""` | Overrides the status page name in the header. Leave empty to use the page name. | | `customSubtitle` | string | max 200 chars | `""` | Optional tagline below the title | ### Display options | Field | Type | Default | Description | |-------|------|---------|-------------| | `showUptimeStats` | boolean | `true` | Show uptime percentage and service counts | | `showServiceUrls` | boolean | `false` | Show the monitored URL below each service name | | `showLastChecked` | boolean | `false` | Show the last check timestamp per service | | `showHistory` | boolean | `true` | Show the recent incidents & maintenance section | | `showPoweredBy` | boolean | `true` | Show "Powered by …" badge in the footer | ## Example — switch to dark timeline layout ```bash curl -X PATCH "$BASE_URL/api/status-pages/db58058e-4b58-4d97-a314-3bb8e279a182/design" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "layout": "timeline", "colorScheme": "dark", "accentColor": "#f59e0b", "pageWidth": "lg" }' ``` ## Example — minimal, no branding, full width ```bash curl -X PATCH "$BASE_URL/api/status-pages/db58058e-4b58-4d97-a314-3bb8e279a182/design" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "layout": "minimal", "colorScheme": "light", "pageWidth": "xl", "showPoweredBy": false, "showUptimeStats": false, "customTitle": "System Status", "customSubtitle": "Live overview of all services" }' ``` ## Response ```json { "designConfig": { "layout": "timeline", "colorScheme": "dark", "accentColor": "#f59e0b", "headerStyle": "simple", "fontFamily": "system", "cardRadius": "md", "pageWidth": "lg", "customTitle": "", "customSubtitle": "", "showPoweredBy": true, "showUptimeStats": true, "showServiceUrls": false, "showLastChecked": false, "showHistory": true } } ``` ## Common errors - `400 Bad Request` — invalid field value (e.g. unknown layout name or malformed hex color) - `401 Unauthorized` — not authenticated - `403 Forbidden` — not an admin - `404 Not found` — status page does not exist ### Verify Status Page Domain URL: https://docs.uptimeify.io/api/status-pages/verify-status-page-domain Description: Verifies DNS TXT records for a custom status page domain. Admin-only. Summary: `POST /api/status-pages/domains/verify` ## Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `domainId` | number | Yes | The domain ID to verify | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/status-pages/domains/verify" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "domainId": 42 }' ``` ## Response (success) ```json { "verified": true, "status": "verified", "domain": { "id": 42, "hostname": "status.example.com", "status": "verified", "role": "status_page", "verificationToken": "abc123-def456-ghi789", "verifiedAt": "2026-05-01T12:00:00.000Z", "createdAt": "2026-05-01T11:00:00.000Z", "updatedAt": "2026-05-01T12:00:00.000Z" } } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `404 Not found` when the domain does not exist ### Tags URL: https://docs.uptimeify.io/api/tags Description: Organize your monitors with tags — create, assign, filter, and manage across all monitor types. Summary: Tags let you label any monitor (website, DNS, ICMP, SMTP, SSH, FTP, IMAP/POP) with one or more color-coded tags and then filter any monitor list by tag. Tags are organization-scoped; readonly members can create and use their own tags but cannot see or modify tags created by others. ## Endpoints - [List Tags](./list-tags) - [Create Tag](./create-tag) - [Update Tag](./update-tag) - [Delete Tag](./delete-tag) - [Assign Tag to Monitor](./assign-tag) - [Remove Tag from Monitor](./remove-tag) - [List Monitor Tags](./list-monitor-tags) ### Assign Tag to Monitor URL: https://docs.uptimeify.io/api/tags/assign-tag Description: Assigns an existing tag to a monitor. The caller needs read access to the monitor and visibility of the tag. The operation is idempotent. Summary: `POST /api/monitor-tags` ## Body ```json { "monitorType": "website", "monitorId": 101, "tagId": 1 } ``` - `monitorType` (required): Type of the monitor. One of: `website` | `dns` | `icmp` | `smtp` | `ssh` | `ftp` | `imap_pop`. - `monitorId` (required): Numeric ID of the monitor. - `tagId` (required): Numeric ID of the tag to assign. This operation is **idempotent**: calling it again when the tag is already assigned returns the existing assignment without error. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST "$BASE_URL/api/monitor-tags" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"monitorType":"website","monitorId":101,"tagId":1}' ``` ## Response ```json { "monitorType": "website", "monitorId": 101, "tagId": 1, "createdAt": "2026-06-29T12:00:00.000Z" } ``` ## Common errors - `400 Bad Request` when `monitorType` is not a supported type - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you do not have read access to the monitor or cannot see the tag - `404 Not Found` when the monitor or tag does not exist ### Create Tag URL: https://docs.uptimeify.io/api/tags/create-tag Description: Creates a new tag in your organization. Readonly members may create tags that are visible only to themselves. Summary: `POST /api/tags` ## Body ```json { "name": "Production", "color": "red" } ``` - `name` (required): Display label for the tag (max 50 characters). - `color` (required): One of the palette keys: `slate` | `red` | `amber` | `green` | `teal` | `blue` | `indigo` | `violet` | `pink` | `gray`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST "$BASE_URL/api/tags" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Production","color":"red"}' ``` ## Response ```json { "id": 1, "publicId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "organizationId": 10, "name": "Production", "color": "red", "createdBy": 42, "createdAt": "2026-06-29T10:00:00.000Z", "updatedAt": "2026-06-29T10:00:00.000Z" } ``` ## Common errors - `400 invalidTagColor` when `color` is not a recognized palette key - `400 Bad Request` when `name` is missing or exceeds the character limit - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Delete Tag URL: https://docs.uptimeify.io/api/tags/delete-tag Description: Deletes a tag and removes it from all monitors it was assigned to. Only the tag owner or an admin may delete a tag. Summary: `DELETE /api/tags/{id}` Path parameter `{id}` is the tag's numeric `id`. Deleting a tag cascades: all monitor-tag assignments for that tag are also removed automatically. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" TAG_ID=1 curl -X DELETE "$BASE_URL/api/tags/$TAG_ID" \ -H "Authorization: Bearer $TOKEN" ``` ## Response Returns `204 No Content` on success. ## Common errors - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you are not the tag owner or an admin - `404 Not Found` when the tag does not exist or is not visible to you ### List Monitor Tags URL: https://docs.uptimeify.io/api/tags/list-monitor-tags Description: Returns all tags assigned to a specific monitor. Readonly members see only their own tags. Summary: `GET /api/monitor-tags` ## Query Parameters - `monitorType` (required): Type of the monitor. One of: `website` | `dns` | `icmp` | `smtp` | `ssh` | `ftp` | `imap_pop`. - `monitorId` (required): Numeric ID of the monitor. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/monitor-tags?monitorType=website&monitorId=101" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": 1, "publicId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "organizationId": 10, "name": "Production", "color": "red", "createdBy": 42, "createdAt": "2026-06-01T08:00:00.000Z", "updatedAt": "2026-06-01T08:00:00.000Z" } ] ``` ## Common errors - `400 Bad Request` when `monitorType` or `monitorId` is missing or invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you do not have read access to the monitor - `404 Not Found` when the monitor does not exist ### List Tags URL: https://docs.uptimeify.io/api/tags/list-tags Description: Returns all tags visible to the caller. Readonly members see only tags they created themselves. Summary: `GET /api/tags` ## Query Parameters - `organizationId` (optional): Defaults to your session organization. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/tags" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json [ { "id": 1, "publicId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "organizationId": 10, "name": "Production", "color": "red", "createdBy": 42, "createdAt": "2026-06-01T08:00:00.000Z", "updatedAt": "2026-06-01T08:00:00.000Z" }, { "id": 2, "publicId": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", "organizationId": 10, "name": "Staging", "color": "amber", "createdBy": 42, "createdAt": "2026-06-10T09:00:00.000Z", "updatedAt": "2026-06-10T09:00:00.000Z" } ] ``` ## Common errors - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Remove Tag from Monitor URL: https://docs.uptimeify.io/api/tags/remove-tag Description: Removes a tag assignment from a monitor. The caller must have read access to the monitor. Summary: `DELETE /api/monitor-tags` ## Body ```json { "monitorType": "website", "monitorId": 101, "tagId": 1 } ``` - `monitorType` (required): Type of the monitor. One of: `website` | `dns` | `icmp` | `smtp` | `ssh` | `ftp` | `imap_pop`. - `monitorId` (required): Numeric ID of the monitor. - `tagId` (required): Numeric ID of the tag to remove. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE "$BASE_URL/api/monitor-tags" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"monitorType":"website","monitorId":101,"tagId":1}' ``` ## Response Returns `204 No Content` on success. ## Common errors - `400 Bad Request` when `monitorType` is not a supported type - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you do not have read access to the monitor - `404 Not Found` when the assignment does not exist ### Update Tag URL: https://docs.uptimeify.io/api/tags/update-tag Description: Updates an existing tag's name or color. Only the tag owner or an admin may update a tag. Summary: `PATCH /api/tags/{id}` Path parameter `{id}` is the tag's numeric `id`. ## Body All fields are optional; send only the fields you want to change. ```json { "name": "Critical", "color": "violet" } ``` - `name` (optional): New display label (max 50 characters). - `color` (optional): One of the palette keys: `slate` | `red` | `amber` | `green` | `teal` | `blue` | `indigo` | `violet` | `pink` | `gray`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" TAG_ID=1 curl -X PATCH "$BASE_URL/api/tags/$TAG_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Critical","color":"violet"}' ``` ## Response ```json { "id": 1, "publicId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "organizationId": 10, "name": "Critical", "color": "violet", "createdBy": 42, "createdAt": "2026-06-01T08:00:00.000Z", "updatedAt": "2026-06-29T11:00:00.000Z" } ``` ## Common errors - `400 invalidTagColor` when `color` is not a recognized palette key - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you are not the tag owner or an admin - `404 Not Found` when the tag does not exist or is not visible to you ### Users URL: https://docs.uptimeify.io/api/users Description: Manage users within your organization. Summary: ## Endpoints - [List Users](./list-users) - [Create User](./create-user) - [Get User](./get-user) - [Update User](./update-user) - [Delete User](./delete-user) ### Create User URL: https://docs.uptimeify.io/api/users/create-user Description: Creates a new user in the organization. Summary: `POST /api/users` ## Request Body ```json { "email": "jane@example.com", "firstName": "Jane", "lastName": "Doe", "role": "user", // "admin" or "user" "password": "temporaryPassword123", // Optional, user can set it later "customerIds": ["11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222"] // Optional: Limit access to specific customers via public IDs } ``` Notes: - `customerIds` accepts customer public IDs and legacy numeric IDs. - Public IDs are the preferred format for new integrations. ## Response Returns the created user object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Delete User URL: https://docs.uptimeify.io/api/users/delete-user Description: Removes a user from the organization. Summary: `DELETE /api/users/:id` ## Response On success: `204 No Content`. ### Get User URL: https://docs.uptimeify.io/api/users/get-user Description: Returns the details of a specific user. Summary: `GET /api/users/:id` ## Response ```json { "id": "user_123", "name": "Max Mustermann", "email": "max@example.com", "role": "admin", "isActive": true, "createdAt": "2023-01-01T00:00:00Z" } ``` ### List Users URL: https://docs.uptimeify.io/api/users/list-users Description: Lists all users in the organization. Summary: `GET /api/users` ## Response ```json { "id": "user_123", "name": "Max Mustermann", "email": "max@example.com", "role": "admin", "isActive": true, "createdAt": "2023-01-01T00:00:00Z" } ``` ### Update User URL: https://docs.uptimeify.io/api/users/update-user Description: Updates the details and permissions of a user. Summary: `PATCH /api/users/:id` ## Request Body ```json { "firstName": "Jane", "lastName": "Smith", "role": "admin", "isActive": true, "customerIds": ["11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222"] // Update the list of assigned customers via public IDs } ``` Notes: - `customerIds` accepts customer public IDs and legacy numeric IDs. - Public IDs are the preferred format for new integrations. ## Response Returns the updated user object. See [Error Codes](/api/error-codes-and-known-pitfalls) for error responses. ### Configurations URL: https://docs.uptimeify.io/api/website-configuration Description: Manage advanced monitoring settings for your websites. Summary: ## Authentication All examples assume a bearer token: ```bash BASE_URL="https://uptimeify.io" TOKEN="" ``` ## Check Configuration ### Update Check Settings `PATCH /api/websites/:websiteId/check-config` Configure which aspects of the website should be monitored. #### Request Body ```json { "checkSslEnabled": true, "checkHttpsRedirectEnabled": true, "checkStatusEnabled": true, "checkSizeEnabled": true, "checkResponseTimeEnabled": true, "checkKeywordEnabled": false, "checkDomainExpiryEnabled": true, "minPageSize": 1024, "maxPageSize": 5242880 } ``` Example (cURL): ```bash curl -X PATCH \ "$BASE_URL/api/websites/101/check-config" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"checkSslEnabled":true,"checkHttpsRedirectEnabled":true,"checkStatusEnabled":true,"checkSizeEnabled":true,"checkResponseTimeEnabled":true,"checkKeywordEnabled":false}' ``` ## Alerting Configuration Alerting-related defaults and feature flags are configured via **organization package configs**. See: - [List Package Configs](../organization/list-package-configs) - [Upsert Package Config](../organization/upsert-package-config) - [Delete Package Config](../organization/delete-package-config) ## Notification Channels ## Maintenance Windows ### List Maintenance Windows `GET /api/maintenance-windows?websiteId=:websiteId` ### Get Maintenance Window `GET /api/maintenance-windows/:id` ### Create Maintenance Window `POST /api/maintenance-windows` ### Update Maintenance Window `PATCH /api/maintenance-windows/:id` ### Delete Maintenance Window `DELETE /api/maintenance-windows/:id` ### Check Maintenance (Website) `GET /api/maintenance-windows/check/:websiteId` ### Check Maintenance (Batch) `POST /api/maintenance-windows/check/batch` ## Endpoints - [Update Check Settings](./update-check-settings) - [List Maintenance Windows](./list-maintenance-windows) - [Get Maintenance Window](./get-maintenance-window) - [Create Maintenance Window](./create-maintenance-window) - [Update Maintenance Window](./update-maintenance-window) - [Delete Maintenance Window](./delete-maintenance-window) - [Check Maintenance (Website)](./check-maintenance-window) - [Check Maintenance (Batch)](./check-maintenance-window-batch) ### Check Maintenance (Website) URL: https://docs.uptimeify.io/api/website-configuration/check-maintenance-window Description: Checks if a website is currently in an active maintenance window. Summary: `GET /api/maintenance-windows/check/:websiteId` This endpoint requires authentication via browser session or API token. ## Parameters - `websiteId` (Path, required): Internal numeric website ID or `websitePublicId` (UUID). ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" API_TOKEN="wsm_your_real_api_token" curl -X GET "$BASE_URL/api/maintenance-windows/check/cd11a84d-96a2-41aa-a957-b1db8ee01b72" \ -H "Authorization: Bearer $API_TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "inMaintenance": true, "activeWindows": [ { "id": 5, "name": "Weekly maintenance", "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "description": "Planned downtime" } ] } ``` ## Common errors - `401 Unauthorized` when no valid session or API token is sent - `403 Forbidden` when the website is outside the allowed customer/organization scope - `400 Invalid Website identifier` when `:websiteId` is neither a positive integer ID nor a UUID - `404 Website not found` when the provided `websitePublicId` does not resolve to a website ### Check Maintenance (Batch) URL: https://docs.uptimeify.io/api/website-configuration/check-maintenance-window-batch Description: Batch-check multiple websites for active maintenance windows. Summary: `POST /api/maintenance-windows/check/batch` This endpoint requires authentication via browser session or API token. ## Request Body ```json { "websiteIds": [101, "cd11a84d-96a2-41aa-a957-b1db8ee01b72", 103] } ``` ### Fields - `websiteIds` ((number|string)[], required): numeric website IDs or `websitePublicId` UUIDs ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" API_TOKEN="wsm_your_real_api_token" curl -X POST "$BASE_URL/api/maintenance-windows/check/batch" \ -H "Authorization: Bearer $API_TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{"websiteIds":[101,"cd11a84d-96a2-41aa-a957-b1db8ee01b72",103]}' ``` ## Example Response ```json { "results": { "101": { "inMaintenance": true, "activeWindows": [ { "id": 5, "name": "Weekly maintenance", "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "description": "Planned downtime" } ] }, "cd11a84d-96a2-41aa-a957-b1db8ee01b72": { "inMaintenance": false, "activeWindows": [] } } } ``` ## Common errors - `400 websiteIds array required` when `websiteIds` is missing/empty - `400 All websiteIds must be valid identifiers` when any entry is neither a positive integer ID nor a UUID - `401 Unauthorized` when no valid session or API token is sent - `403 Forbidden` when at least one website is outside the allowed customer/organization scope - `404 Website not found` when a provided `websitePublicId` does not resolve to a website ### Create Maintenance Window URL: https://docs.uptimeify.io/api/website-configuration/create-maintenance-window Description: Creates a new maintenance window. Summary: `POST /api/maintenance-windows` Important: You must provide **exactly one** target ID (e.g. `websiteId` *or* `icmpMonitorId`, `smtpMonitorId`, `sshMonitorId`, `ftpMonitorId`, `imapPopMonitorId`). All target IDs and `customerId` accept either the internal numeric ID or the matching public UUID. ## Authentication Requires a valid session or API token. - Header: `Authorization: Bearer ` Note: Global supporter users are not allowed to create maintenance windows (`403`). Read-only users are allowed. ## Request Body ```json { "websiteId": "521e3338-4597-4d1d-8eeb-dc56d271e71c", "name": "Server Upgrade", "description": "Planned downtime", "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true } ``` ### Fields Target (exactly one required): - `websiteId` (number|string) - `icmpMonitorId` (number|string) - `smtpMonitorId` (number|string) - `sshMonitorId` (number|string) - `ftpMonitorId` (number|string) - `imapPopMonitorId` (number|string) - `customerId` (number|string, optional) Identifier rule: Internal numeric IDs or public UUIDs are accepted. Other fields: - `name` (string, required) - `description` (string, optional) - Max length: 2000 - If omitted (or empty), it is stored as `null`. - `startTime` (string/date, required) - `endTime` (string/date, required) - Must be after `startTime`. - `isRecurring` (boolean, optional) - Default: `false` - `recurrencePattern` (object, optional) - Stored as JSON. - Typical keys include `frequency`, `interval`, `daysOfWeek`, `dayOfMonth`, `endRecurrenceDate`. - `isActive` (boolean, optional) - Default: `true` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST \ "$BASE_URL/api/maintenance-windows" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"websiteId":"521e3338-4597-4d1d-8eeb-dc56d271e71c","name":"Server Upgrade","description":"Planned downtime","startTime":"2026-02-25T02:00:00.000Z","endTime":"2026-02-25T04:00:00.000Z","isRecurring":true,"recurrencePattern":{"frequency":"weekly","interval":1,"daysOfWeek":[1]},"isActive":true}' ``` ## Example Response ```json { "id": 5, "websiteId": 101, "icmpMonitorId": null, "smtpMonitorId": null, "sshMonitorId": null, "ftpMonitorId": null, "imapPopMonitorId": null, "customerId": 12, "name": "Server Upgrade", "description": "Planned downtime", "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true, "createdBy": "", "createdAt": "2026-02-20T10:00:00.000Z", "updatedAt": "2026-02-20T10:00:00.000Z" } ``` ## Common Errors - `400 Exactly one target ID must be provided` if no or multiple target IDs are sent - `400 Invalid Website identifier` or the corresponding target error if an identifier is neither an integer ID nor a UUID - `400 End time must be after start time` if `endTime <= startTime` - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access (or are a global supporter) ### Delete Maintenance Window URL: https://docs.uptimeify.io/api/website-configuration/delete-maintenance-window Description: Deletes a maintenance window. Summary: `DELETE /api/maintenance-windows/:id` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` Note: Global supporter users are not allowed to delete maintenance windows (`403`). Read-only users are allowed. ## Parameters - `id` (Path, required): Maintenance window ID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE \ "$BASE_URL/api/maintenance-windows/5" \ -H "Authorization: Bearer $TOKEN" ``` ## Example Response ```json { "success": true } ``` ## Common Errors - `400 Invalid maintenance window ID` if `:id` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access - `404 Maintenance window not found` if the maintenance window does not exist ### Get Maintenance Window URL: https://docs.uptimeify.io/api/website-configuration/get-maintenance-window Description: Returns a single maintenance window by ID (including its target relation). Summary: `GET /api/maintenance-windows/:id` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` Note (API token scope): If you use a customer-scoped API token, the window must belong to that customer. ## Parameters - `id` (Path, required): Maintenance window ID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/maintenance-windows/5" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "id": 5, "websiteId": 101, "icmpMonitorId": null, "smtpMonitorId": null, "sshMonitorId": null, "ftpMonitorId": null, "imapPopMonitorId": null, "customerId": 12, "name": "Weekly maintenance", "description": "Planned downtime", "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true, "createdBy": "", "createdAt": "2026-02-20T10:00:00.000Z", "updatedAt": "2026-02-20T10:00:00.000Z", "website": { "id": 101, "url": "https://example.com" } } ``` Note: Depending on the target, the response may also include one of these relations: `icmpMonitor`, `smtpMonitor`, `sshMonitor`, `ftpMonitor`, `imapPopMonitor`. Nested `customer` objects are not returned. ## Common errors - `400 Invalid maintenance window ID` when `:id` is invalid - `404 Maintenance window not found` when the window does not exist - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the target/customer - `500 Maintenance window target is missing` if the window has no valid target ### List Maintenance Windows URL: https://docs.uptimeify.io/api/website-configuration/list-maintenance-windows Description: Returns maintenance windows scoped to your organization by default. Summary: `GET /api/maintenance-windows` You can filter by a specific target (e.g. `websiteId`) or by customer/organization. ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` ## Query Parameters - `websiteId` (optional) - `customerId` (optional) - `organizationId` (optional, defaults to your session organization) - `activeOnly` (optional): set to `true` to only return active windows - Target filters (optional, exactly one is typically used when narrowing down): - `icmpMonitorId`, `smtpMonitorId`, `sshMonitorId`, `ftpMonitorId`, `imapPopMonitorId` Note: When `websiteId` is provided, access is enforced for that website. Note (API token scope): If you use a customer-scoped API token, results are restricted to that customer. Providing a different `customerId` returns `403`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET \ "$BASE_URL/api/maintenance-windows?websiteId=101" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json [ { "id": 5, "websiteId": 101, "icmpMonitorId": null, "smtpMonitorId": null, "sshMonitorId": null, "ftpMonitorId": null, "imapPopMonitorId": null, "customerId": 12, "customerName": "Acme Corp", "name": "Weekly maintenance", "description": "Planned downtime", "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true, "createdBy": "", "createdAt": "2026-02-20T10:00:00.000Z", "updatedAt": "2026-02-20T10:00:00.000Z", "website": { "id": 101, "url": "https://example.com" } } ] ``` Note: The list endpoint only includes the `website` relation (when `websiteId` is set). It does not include nested `customer` objects or monitor relations. A lightweight top-level `customerName` is included for display/filtering. ## Common Errors - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access ### Update Check Settings URL: https://docs.uptimeify.io/api/website-configuration/update-check-settings Description: Configure which aspects of the website should be monitored. Summary: `PATCH /api/websites/:websiteId/check-config` ## Request Body ```json { "checkSslEnabled": true, "checkHttpsRedirectEnabled": true, "checkStatusEnabled": true, "checkSizeEnabled": true, "checkResponseTimeEnabled": true, "checkKeywordEnabled": false, "checkDomainExpiryEnabled": true, "minPageSize": 1024, "maxPageSize": 5242880 } ``` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH \ "$BASE_URL/api/websites/101/check-config" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"checkSslEnabled":true,"checkHttpsRedirectEnabled":true,"checkStatusEnabled":true,"checkSizeEnabled":true,"checkResponseTimeEnabled":true,"checkKeywordEnabled":false,"checkDomainExpiryEnabled":true,"minPageSize":1024,"maxPageSize":5242880}' ``` ## Example Response ```json { "success": true } ``` ## Common errors - `400 Invalid website ID` when `:websiteId` is invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you do not have write access to the website - `404 Website not found` when the website does not exist ### Update Maintenance Window URL: https://docs.uptimeify.io/api/website-configuration/update-maintenance-window Description: Updates an existing maintenance window. Summary: `PATCH /api/maintenance-windows/:id` ## Authentication Requires a valid session. - Header: `Authorization: Bearer ` Note: Global supporter users are not allowed to update maintenance windows (`403`). Read-only users are allowed. ## Parameters - `id` (Path, required): Maintenance window ID. ## Request Body All fields are optional. ```json { "name": "Server Upgrade (updated)", "description": null, "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true } ``` Notes: - You cannot change the target IDs (`websiteId`, `icmpMonitorId`, ...). Only the window fields can be updated. - `description` can be set to `null` to clear it. - If you update `startTime` and/or `endTime`, `endTime` must be after `startTime`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH \ "$BASE_URL/api/maintenance-windows/5" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Server Upgrade (updated)","description":null,"startTime":"2026-02-25T02:00:00.000Z","endTime":"2026-02-25T04:00:00.000Z","isRecurring":true,"recurrencePattern":{"frequency":"weekly","interval":1,"daysOfWeek":[1]},"isActive":true}' ``` ## Example Response ```json { "id": 5, "websiteId": 101, "icmpMonitorId": null, "smtpMonitorId": null, "sshMonitorId": null, "ftpMonitorId": null, "imapPopMonitorId": null, "customerId": 12, "name": "Server Upgrade (updated)", "description": null, "startTime": "2026-02-25T02:00:00.000Z", "endTime": "2026-02-25T04:00:00.000Z", "isRecurring": true, "recurrencePattern": { "frequency": "weekly", "interval": 1, "daysOfWeek": [1] }, "isActive": true, "createdBy": "", "createdAt": "2026-02-20T10:00:00.000Z", "updatedAt": "2026-02-21T11:00:00.000Z" } ``` ## Common Errors - `400 Invalid maintenance window ID` if `:id` is invalid - `400 End time must be after start time` if you update the time range to an invalid value - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have access - `404 Maintenance window not found` if the maintenance window does not exist ### Website Management URL: https://docs.uptimeify.io/api/websites Description: Manage monitored websites. Summary: Path-based website endpoints use `websitePublicId` UUIDs. ## Endpoints - [List Websites](./list-websites) - [Create Website](./create-website) - [Get Website](./get-website) - [Get Website Details](./get-website-details) - [Update Website](./update-website) - [Change Status](./change-status) - [Delete Website](./delete-website) ### Change Website Status URL: https://docs.uptimeify.io/api/websites/change-status Description: Changes the monitoring status of a website. Summary: `PATCH /api/websites/:websitePublicId` There is no dedicated `.../status` endpoint — status changes are part of `PATCH /api/websites/:websitePublicId`. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/websites/9a3d4d4d-7a4b-4f37-a9df-2a6f6d9d7a10" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "status": "maintenance" }' ``` ## Request Body ```json { "status": "active" } ``` Allowed values: - `active` - `inactive` (you may also send `paused`, it will be mapped to `inactive`) - `maintenance` ## Response Returns the updated website record. ## Common errors - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot write to the website - `403 Active website limit reached...` when switching to `active` would exceed the customer/package limit ### Create Website URL: https://docs.uptimeify.io/api/websites/create-website Description: Creates a new website monitor for a customer. Summary: `POST /api/websites` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST "$BASE_URL/api/websites" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "customerId": "059e1469-0f05-4c93-bd4d-89c45bb2afd9", "name": "New Landing Page", "url": "https://landing.example.com", "monitoringType": "combined", "checkInterval": 5 }' ``` ## Request Body ### Core fields | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `customerId` | number\|string | Yes | — | Customer public ID (preferred) or legacy numeric ID | | `name` | string | Yes | — | Display name (1–255 chars) | | `url` | string | Yes* | — | URL to monitor (1–2048 chars). Required for non-heartbeat monitors. For DNS monitors, use a hostname without protocol. | | `monitoringType` | string | No | `combined` | `combined`, `http_status`, `ssl_check`, `playwright`, `heartbeat`, `dns` | | `status` | string | No | `active` | `active`, `inactive`, `maintenance` (`paused` accepted, mapped to `inactive`) | | `checkInterval` | number | No | 30 | Check interval in minutes (1–60, min depends on package) | | `timeoutSeconds` | number | No | 30 | Request timeout in seconds (1–60) | | `expectedStatusCodes` | string | No | `200,301,302` | Comma-separated expected HTTP status codes | | `allowedCheckCountryCodes` | string[]\|null | No | org default | Array of 2-letter country codes to restrict monitoring locations | | `searchTerm` | string\|null | No | null | Keyword to search for in response body (max 255 chars) | | `customFields` | object\|null | No | null | Custom field values as key-value pairs | | `managementType` | string | No | `managed` | Ownership class: `managed` or `self_service` — see [Managed vs. Self-Service](/monitoring/managed-vs-self-service). Only organization admins may choose it; customer-scoped creators always get `self_service` (requires `allowSelfService` and free quota). | ### Authentication | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `authMode` | string | No | `none` | `none`, `authorization_header`, `basic` | | `authorizationHeader` | string\|null | No | null | Required when `authMode` is `authorization_header` (1–4096 chars). Encrypted at rest. | | `basicAuthUsername` | string\|null | No | null | Required when `authMode` is `basic` (1–255 chars) | | `basicAuthPassword` | string\|null | No | null | Required when `authMode` is `basic` (1–4096 chars). Encrypted at rest. | ### HTTP Request Configuration | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `httpMethod` | string | No | `GET` | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS` | | `customHeaders` | object\|null | No | null | Custom HTTP headers as key-value pairs. Keys: 1–100 chars, values: max 8192 chars. Encrypted at rest. | | `requestBody` | string\|null | No | null | Request body for POST/PUT/PATCH requests (max 100KB). Encrypted at rest. | | `followRedirects` | boolean | No | true | Whether to follow HTTP redirects | | `cookieHandling` | string | No | `none` | `none` or `jar` (maintain cookie jar across redirects) | ### mTLS (Mutual TLS) | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `mtlsEnabled` | boolean | No | false | Enable mutual TLS authentication | | `mtlsClientCert` | string\|null | No | null | Required when `mtlsEnabled` is true (1–100000 chars). Encrypted at rest. | | `mtlsClientKey` | string\|null | No | null | Required when `mtlsEnabled` is true (1–100000 chars). Encrypted at rest. | ### Playwright Monitoring | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `playwrightScript` | string\|null | No* | null | Required when `monitoringType` is `playwright` (1–20000 chars) | | `playwrightEnv` | object\|null |… ### Delete Website URL: https://docs.uptimeify.io/api/websites/delete-website Description: Irrevocably removes a website and its monitoring history. Summary: `DELETE /api/websites/:websitePublicId` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X DELETE "$BASE_URL/api/websites/9a3d4d4d-7a4b-4f37-a9df-2a6f6d9d7a10" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "success": true } ``` ## Common errors - `400 Website public ID (UUID) required` when `:websitePublicId` is invalid - `401 Unauthorized` when you are not logged in - `500 Failed to delete website` on server errors ### Get Website URL: https://docs.uptimeify.io/api/websites/get-website Description: Returns a single website (basic/sanitized). Sensitive fields like encrypted credentials are removed. Summary: `GET /api/websites/:websitePublicId` If you need the full “mega” representation (including additional computed/status fields), use: - `GET /api/websites/:websitePublicId/details` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites/9a3d4d4d-7a4b-4f37-a9df-2a6f6d9d7a10" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "id": 101, "organizationId": 1, "customerId": 1, "name": "Main Marketing Site", "url": "https://example.com", "status": "active", "monitoringType": "combined", "checkInterval": 1, "createdAt": "2026-02-26T12:00:00.000Z", "updatedAt": "2026-02-26T12:00:00.000Z" } ``` ## Common errors - `400 Website public ID (UUID) required` when `:websitePublicId` is missing/invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the website - `404 Not Found` when the website does not exist ### Get Website Details URL: https://docs.uptimeify.io/api/websites/get-website-details Description: Returns the website detail page data in one call (mega endpoint). This includes monitoring stats, alert history, incident history, monitoring chart data, and maintenance windows. Summary: `GET /api/websites/:websitePublicId/details` ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites/9a3d4d4d-7a4b-4f37-a9df-2a6f6d9d7a10/details?range=day" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Query Parameters - `range` (optional): `day` | `week` | `month` | `year` (default: `day`) - `date` (optional): reference date for calendar views - `startDate` / `endDate` (optional): custom date window for zoomed views - `granularity` (optional): e.g. `minute` for non-aggregated data (when supported) ## Response ```json { "website": { "id": 101, "name": "Main Marketing Site", "url": "https://example.com", "status": "active", "monitoringType": "combined", "customerId": 1 }, "uptimeStats": { "day": "100.00", "month": "99.95", "year": "99.90", "dayAvgResponse": 125, "monthAvgResponse": 118, "yearAvgResponse": 120 }, "monitoringData": { "responseTimeData": [], "statusData": [], "uptimePercentage": "99.95", "checkSuccessRatePercentage": "99.80", "totalChecks": 100, "successfulChecks": 99 }, "incidents": { "history": [], "total": 0, "ongoing": 0, "totalDowntime": "0m" }, "alerts": { "history": [], "total": 0, "notificationContext": null }, "maintenance": { "inMaintenance": false, "activeWindows": [], "allWindows": [] } } ``` ## Common errors - `400 Invalid website public ID (UUID)` when `:websitePublicId` is invalid - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you have no access to the website - `500 Failed to fetch website details` on server errors ### List Websites URL: https://docs.uptimeify.io/api/websites/list-websites Description: Lists websites within an organization (paginated). Results are scoped by your session/permissions. Summary: `GET /api/websites` ## Query Parameters - `organizationId` (optional): Defaults to your session organization. - `customerId` (optional): Filter websites by customer. - `search` (optional): Search by website/customer fields. - `monitoringType` (optional): `combined` | `http_status` | `ssl_check` | `playwright` | `heartbeat` | `dns` - `excludeMonitoringType` (optional): same values as `monitoringType` - `page` (optional, default: `1`) - `perPage` (optional, default: `50`, max: `200`) ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X GET "$BASE_URL/api/websites?organizationId=1&page=1&perPage=50" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Response ```json { "items": [ { "id": 101, "publicId": "11111111-1111-4111-8111-111111111111", "customerId": 1, "customerPublicId": "22222222-2222-4222-8222-222222222222", "customerName": "Acme Corp", "name": "Main Marketing Site", "url": "https://example.com", "status": "active", "monitoringType": "combined", "checkInterval": 1, "createdAt": "2026-02-26T12:00:00.000Z" } ], "total": 1, "page": 1, "perPage": 50 } ``` Each item contains flat `customerName` and `customerPublicId` fields, not a full embedded `customer` object. ## Common errors - `400 Invalid customerId` when `customerId` is invalid - `400 Invalid monitoringType` when `monitoringType` is not supported - `401 Unauthorized` when you are not logged in - `403 Forbidden` when you cannot access the organization ### Trigger Website Check URL: https://docs.uptimeify.io/api/websites/trigger-check Description: Triggers an immediate check of a website across eligible monitoring locations. Summary: `POST /api/websites/:websitePublicId/trigger-check` ## Authentication Requires a valid session with write access to the website. - Header: `Authorization: Bearer ` ## Parameters - `websitePublicId` (Path, required): Website public UUID. ## Example (cURL) ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X POST \ "$BASE_URL/api/websites/6bfec6f6-245a-47ce-843b-157d97d56f88/trigger-check" \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/json" ``` ## Example Response ```json { "success": true, "message": "Check triggered successfully", "websiteId": 123 } ``` The check is enqueued for the website's active monitoring locations; results land in the check history a few seconds later. ## Common Errors - `400 Website public ID (UUID) required` if `:websitePublicId` is invalid - `401 Unauthorized` if you are not authenticated - `403 Forbidden` if you do not have write access to the website - `503 No active monitoring locations available` ### Update Website URL: https://docs.uptimeify.io/api/websites/update-website Description: Updates a website. Supports both partial updates (only sent fields are changed) and full updates (all required fields must be present). Summary: `PATCH /api/websites/:websitePublicId` A request is treated as a **full update** when `customerId`, `name`, and `url` are all present in the body. Otherwise, it is treated as a partial update. ## Example (cURL) — Partial update ```bash BASE_URL="https://uptimeify.io" TOKEN="" curl -X PATCH "$BASE_URL/api/websites/9a3d4d4d-7a4b-4f37-a9df-2a6f6d9d7a10" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "name": "Updated Website Name", "checkInterval": 5, "timeoutSeconds": 10 }' ``` ## Example (cURL) — Full update with HTTP configuration ```bash curl -X PATCH "$BASE_URL/api/websites/9a3d4d4d-7a4b-4f37-a9df-2a6f6d9d7a10" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "customerId": 5, "name": "API Endpoint Monitor", "url": "https://api.example.com/health", "httpMethod": "POST", "customHeaders": { "X-API-Key": "abc123", "Content-Type": "application/json" }, "requestBody": "{\"check\": true}", "followRedirects": false, "cookieHandling": "jar", "mtlsEnabled": true, "mtlsClientCert": "-----BEGIN CERTIFICATE-----\n...", "mtlsClientKey": "-----BEGIN PRIVATE KEY-----\n..." }' ``` ## Request Body All fields are optional for partial updates. For full updates, `customerId`, `name`, and `url` are required. ### Core fields | Field | Type | Description | |-------|------|-------------| | `customerId` | number\|string | Customer public ID (preferred) or legacy numeric ID | | `name` | string | Display name (1–255 chars) | | `url` | string | URL to monitor (1–2048 chars). For DNS monitors, use hostname without protocol. | | `monitoringType` | string | `combined`, `http_status`, `ssl_check`, `playwright`, `heartbeat`, `dns` | | `status` | string | `active`, `inactive`, `maintenance` (`paused` → `inactive`) | | `checkInterval` | number | Check interval in minutes (1–60) | | `timeoutSeconds` | number | Request timeout in seconds (1–60) | | `expectedStatusCodes` | string | Comma-separated expected HTTP status codes | | `allowedCheckCountryCodes` | string[]\|null | Array of 2-letter country codes, or null to reset to org default | | `searchTerm` | string\|null | Keyword to search for (null clears it) | | `customFields` | object\|null | Custom field values | | `managementType` | string | Ownership class: `managed` or `self_service` — see [Managed vs. Self-Service](/monitoring/managed-vs-self-service). Changing the class is organization-admin-only; flipping to `self_service` requires `allowSelfService` and free quota. | ### Authentication | Field | Type | Description | |-------|------|-------------| | `authMode` | string | `none`, `authorization_header`, `basic`. Setting to `none` clears auth credentials. | | `authorizationHeader` | string\|null | Required when `authMode` is `authorization_header`. Encrypted at rest. | | `basicAuthUsername` | string\|null | Required when `authMode` is `basic`. | | `basicAuthPassword` | string\|null | Required when `authMode` is `basic`. Encrypted at rest. | ### HTTP Request Configuration | Field | Type | Description | |-------|------|-------------| | `httpMethod` | string | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS` | | `customHeaders` | object\|null | Custom HTTP headers (keys: 1–100 chars, values: max 8192 chars). Null clears them. Encrypted at rest. | | `requestBody` | string\|null | Request body for POST/PUT/PATCH (max 100KB). Null clears it. Encrypted at rest. | | `followRedirects` | boolean | Whether to follow HTTP redirects | | `cookieHandling` | string | `none` or `jar` (maintain cookie jar across redirects) | ### mTLS (Mutual TLS) | Field | Type | Description | |-------|------|-------------| | `mtlsEnabled` | boolean | Enable mutual TLS authentication. Setting to false clears cert and key. | | `mtlsClientCert` | string\|null | Client certificate (max 100KB). Required when `mtlsEnabled` is true. Encrypted at rest. | | `mtlsClientKey` | string\|null | Clien… ### Whitelabel & Branding URL: https://docs.uptimeify.io/api/whitelabel Description: Customize your organization's product name, theme colors, logos, favicons, and custom domains. All whitelabel endpoints require admin or global admin role. Summary: ## Authentication All whitelabel endpoints require session authentication (not API tokens): ```bash BASE_URL="https://uptimeify.io" ``` ## Endpoints ### Branding - [Get Branding](./get-branding) - [Update Branding](./update-branding) - [Upload Branding Asset](./upload-branding) ### Domains - [List Domains](./list-domains) - [Add Domain](./add-domain) - [Verify Domain](./verify-domain) - [Activate Domain](./activate-domain) - [Delete Domain](./delete-domain) ### Activate Domain URL: https://docs.uptimeify.io/api/whitelabel/activate-domain Description: Activates a verified custom domain. Optionally sets it as the primary domain. Admin-only. Summary: `POST /api/organization/whitelabel/domains/activate` ## Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `domainId` | number | Yes | — | The verified domain ID to activate | | `makePrimary` | boolean | No | auto | Set this domain as primary. Auto-set to `true` if no primary exists. | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/organization/whitelabel/domains/activate" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "domainId": 2, "makePrimary": true }' ``` ## Response ```json { "activated": true, "domain": { "id": 2, "hostname": "app.example.com", "status": "active", "role": "app", "isPrimary": true, "verificationToken": "xyz789-abc456", "verifiedAt": "2026-04-15T12:30:00.000Z", "createdAt": "2026-04-15T12:00:00.000Z", "updatedAt": "2026-04-15T13:00:00.000Z" } } ``` ## Common errors - `400 Domain must be verified before activation` - `404 Domain not found` ### Add Domain URL: https://docs.uptimeify.io/api/whitelabel/add-domain Description: Adds a custom domain for whitelabeling. Creates a pending DNS verification record. The first domain is automatically set as primary. Requires admin role. Summary: `POST /api/organization/whitelabel/domains` ## Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `hostname` | string | Yes | Custom domain hostname (3–253 chars). No wildcards. | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/organization/whitelabel/domains" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "hostname": "app.example.com" }' ``` ## Response ```json { "domain": { "id": 2, "hostname": "app.example.com", "status": "pending", "role": "app", "isPrimary": false, "verificationToken": "xyz789-abc456", "verifiedAt": null, "createdAt": "2026-04-15T12:00:00.000Z", "updatedAt": "2026-04-15T12:00:00.000Z" }, "dns": { "txtName": "_uptimeify-verify.app.example.com", "txtValue": "xyz789-abc456" } } ``` Add a DNS TXT record with the `txtName` and `txtValue`, then call [Verify Domain](./verify-domain). ## Common errors - `400 Invalid hostname` when hostname format is wrong - `400 This hostname is reserved` when hostname matches the main platform - `400 Wildcard domains are not supported` - `409 Hostname already exists` ### Delete Domain URL: https://docs.uptimeify.io/api/whitelabel/delete-domain Description: Deletes a custom domain. If the deleted domain was primary, the next available domain is promoted to primary. Admin-only. Summary: `DELETE /api/organization/whitelabel/domains/:id` ## Example (cURL) ```bash curl -X DELETE "$BASE_URL/api/organization/whitelabel/domains/2" \ -H "Cookie: $SESSION_COOKIE" ``` ## Response ```json { "success": true } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin - `404 Domain not found` ### Get Branding URL: https://docs.uptimeify.io/api/whitelabel/get-branding Description: Returns the organization's branding configuration, including product name, theme colors, and signed URLs for logos and favicons. Requires admin role. Summary: `GET /api/organization/whitelabel/branding` ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/organization/whitelabel/branding" \ -H "Cookie: $SESSION_COOKIE" \ -H "Accept: application/json" ``` ## Response ```json { "branding": { "productName": "Acme Monitor", "hideProductName": false, "logoObjectKey": "branding/org-1/logo/light/1710000000-logo.svg", "logoObjectKeyLight": "branding/org-1/logo/light/1710000000-logo.svg", "logoObjectKeyDark": "branding/org-1/logo/dark/1710000000-logo-dark.svg", "hideLogos": false, "faviconObjectKey": "branding/org-1/favicon/light/1710000000-favicon.ico", "faviconObjectKeyLight": "branding/org-1/favicon/light/1710000000-favicon.ico", "faviconObjectKeyDark": "branding/org-1/favicon/dark/1710000000-favicon-dark.ico", "themePrimary": "#43B1AE", "themeSecondary": null, "logoUrl": "https://s3.example.com/branding/org-1/logo/light/1710000000-logo.svg?...", "logoLightUrl": "https://s3.example.com/branding/org-1/logo/light/1710000000-logo.svg?...", "logoDarkUrl": "https://s3.example.com/branding/org-1/logo/dark/1710000000-logo-dark.svg?...", "faviconUrl": "https://s3.example.com/branding/org-1/favicon/light/1710000000-favicon.ico?...", "faviconLightUrl": "https://s3.example.com/branding/org-1/favicon/light/1710000000-favicon.ico?...", "faviconDarkUrl": "https://s3.example.com/branding/org-1/favicon/dark/1710000000-favicon-dark.ico?...", "updatedAt": "2026-03-01T10:00:00.000Z" } } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin ### List Domains URL: https://docs.uptimeify.io/api/whitelabel/list-domains Description: Returns all custom app domains for the organization. Only domains with role app are returned. Requires admin role. Summary: `GET /api/organization/whitelabel/domains` ## Example (cURL) ```bash curl -X GET "$BASE_URL/api/organization/whitelabel/domains" \ -H "Cookie: $SESSION_COOKIE" \ -H "Accept: application/json" ``` ## Response ```json { "domains": [ { "id": 1, "hostname": "app.example.com", "status": "active", "role": "app", "isPrimary": true, "verificationToken": "abc123-def456", "verifiedAt": "2026-01-15T10:00:00.000Z", "createdAt": "2026-01-14T08:00:00.000Z", "updatedAt": "2026-01-15T10:00:00.000Z" } ] } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin ### Update Branding URL: https://docs.uptimeify.io/api/whitelabel/update-branding Description: Updates the organization's branding configuration. All fields are optional — only sent fields are updated. Setting productName or theme colors to null clears them. Requires admin role. Summary: `PATCH /api/organization/whitelabel/branding` Theme colors accept CSS custom property tokens (e.g. `--color-red-500`) or hex colors (e.g. `#43B1AE`). Invalid values are rejected. ## Request Body (all optional) | Field | Type | Description | |-------|------|-------------| | `productName` | string\|null | Product display name (1–80 chars). `null` clears it. | | `hideProductName` | boolean | Hide the product name in the UI | | `hideLogos` | boolean | Hide all logos in the UI | | `themePrimary` | string\|null | Primary theme color (hex or CSS variable). `null` clears it. | | `themeNeutral` | string\|null | Neutral/secondary theme color (hex or CSS variable). `null` clears it. | ## Example (cURL) ```bash curl -X PATCH "$BASE_URL/api/organization/whitelabel/branding" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "productName": "Acme Monitor", "themePrimary": "#43B1AE", "hideProductName": false }' ``` ## Response ```json { "branding": { "productName": "Acme Monitor", "hideProductName": false, "hideLogos": false, "themePrimary": "#43B1AE", "themeSecondary": null, "updatedAt": "2026-04-15T12:00:00.000Z" } } ``` ## Common errors - `401 Unauthorized` when not authenticated - `403 Forbidden` when not an admin ### Upload Branding Asset URL: https://docs.uptimeify.io/api/whitelabel/upload-branding Description: Uploads a logo or favicon as a base64 data URL. Assets are stored in S3 and the branding record is updated automatically. Requires admin role. Summary: `POST /api/organization/whitelabel/branding/upload` **Logo** types: `logo`, `logoLight`, `logoDark` — accepts PNG, JPEG, WebP, SVG (max 2 MB). **Favicon** types: `favicon`, `faviconLight`, `faviconDark` — accepts PNG, SVG, ICO (max 512 KB). Legacy `logo` is treated as `logoLight`, and `favicon` as `faviconLight`. ## Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `kind` | string | Yes | `logo`, `logoLight`, `logoDark`, `favicon`, `faviconLight`, `faviconDark` | | `fileName` | string | Yes | Original file name (1–200 chars) | | `dataUrl` | string | Yes | Base64 data URL (`data:*/*;base64,...`) | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/organization/whitelabel/branding/upload" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "kind": "logoLight", "fileName": "logo.svg", "dataUrl": "data:image/svg+xml;base64,PHN2Zy..." }' ``` ## Response ```json { "success": true, "uploaded": { "kind": "logo", "objectKey": "branding/org-1/logo/light/1710000000-logo.svg", "contentType": "image/svg+xml", "bytes": 1234, "publicUrl": "https://s3.example.com/branding/org-1/logo/light/1710000000-logo.svg?..." }, "branding": { "productName": "Acme Monitor", "hideProductName": false, "logoUrl": "https://s3.example.com/...", "themePrimary": "#43B1AE", "updatedAt": "2026-04-15T12:00:00.000Z" } } ``` ## Common errors - `400 Invalid dataUrl` when the data URL format is wrong - `400 Unsupported contentType` when the content type is not allowed for the asset kind - `413 File too large` when exceeding size limits - `503 Whitelabel asset storage is not configured` when S3 is not set up ### Verify Domain URL: https://docs.uptimeify.io/api/whitelabel/verify-domain Description: Verifies DNS TXT records for a custom domain. Admin-only. Summary: `POST /api/organization/whitelabel/domains/verify` ## Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `domainId` | number | Yes | The domain ID to verify | ## Example (cURL) ```bash curl -X POST "$BASE_URL/api/organization/whitelabel/domains/verify" \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "domainId": 2 }' ``` ## Response (success) ```json { "verified": true, "status": "verified", "domain": { "id": 2, "hostname": "app.example.com", "status": "verified", "role": "app", "isPrimary": false, "verificationToken": "xyz789-abc456", "verifiedAt": "2026-04-15T12:30:00.000Z", "createdAt": "2026-04-15T12:00:00.000Z", "updatedAt": "2026-04-15T12:30:00.000Z" } } ``` ## Common errors - `400 TXT verification failed (token not found)` when DNS record is missing or has wrong value - `400 Domain has no verification token` - `404 Domain not found` ## Examples ### Examples URL: https://docs.uptimeify.io/examples Description: Practical examples for common workflows with customers, websites, and monitors. Summary: This page has moved into the API documentation. Continue here: - [Examples (API)](/api/examples) - [Create a customer + website](/api/examples/create-customer-and-website) - [Delete a customer including all websites](/api/examples/delete-customer-and-all-websites) - [Create a customer + all monitor types](/api/examples/create-customer-and-all-monitors) - [Create a customer + multiple monitors](/api/examples/create-customer-and-multiple-monitors) ### Create a customer + all monitor types URL: https://docs.uptimeify.io/examples/create-customer-and-all-monitors Description: Example automation: create one website and then create one monitor of each type. Summary: This page has moved into the API documentation. Continue here: - [Create a customer + all monitor types (API)](/api/examples/create-customer-and-all-monitors) ### Create a customer + multiple monitors URL: https://docs.uptimeify.io/examples/create-customer-and-multiple-monitors Description: Example: create a customer and set up multiple monitors (same type and mixed types). Summary: This page has moved into the API documentation. Continue here: - [Create a customer + multiple monitors (API)](/api/examples/create-customer-and-multiple-monitors) ### Create a customer + website URL: https://docs.uptimeify.io/examples/create-customer-and-website Description: End-to-end example: create a customer and then create the first website. Summary: This page has moved into the API documentation. Continue here: - [Create a customer + website (API)](/api/examples/create-customer-and-website) ### Delete a customer including all websites URL: https://docs.uptimeify.io/examples/delete-customer-and-all-websites Description: Safe deletion flow: remove websites first, then delete the customer. Summary: This page has moved into the API documentation. Continue here: - [Delete a customer including all websites (API)](/api/examples/delete-customer-and-all-websites) ## Incidents ### Incidents URL: https://docs.uptimeify.io/incidents Description: Incidents are created automatically when monitoring detects a problem with a website or service. They are the foundation for alerting, reporting, and the public Status Pages. Summary: ## Where to find incidents - **Incidents overview**: `/incidents` - **Per website / monitor**: most detail pages include an incident history tab ## Incident lifecycle Incidents have two primary states: - `open` — the issue is still ongoing - `resolved` — the service recovered and the incident was closed (automatically, once checks pass again) ## What an incident contains Depending on the check type, an incident can include: - **Type / severity** — for example `downtime`, `http_status`, `performance`, `ssl_warning`, `ssl_expiry` - **Start / resolved time** - **HTTP status code** (if applicable) - **Response time (ms)** (if applicable) - **Error message** — network errors, timeouts, parsing failures, etc. - **Last notified timestamp** — used for notification reminders ## Incident details (timeline & evidence) From the incidents list, open the **details modal** to see: - A **timeline** of confirmation → outage → recovery - The **evidence check** (the monitoring check that served as proof) - An optional **traceroute excerpt** - An optional **screenshot** (when available) This answers "what exactly happened?" without digging through raw logs. ## How incidents map to status page state If the customer has a public [status page](/status-pages), open incidents change the displayed service state: | Incident situation | Status page `state` | |--------------------|---------------------| | No open incidents | `operational` | | Only **SSL warning** incidents open | `warning` | | Any other open incident (downtime, http_status, performance, …) | `degraded` | | Active maintenance window, no open incidents | `maintenance` | The overall page banner reflects the most severe state across all services. See [Status Pages → How the public state is derived](/status-pages#how-the-public-state-is-derived). ## Inconclusive checks (browser verification timeouts) Some sites use bot protection / browser verification that can time out. In these cases Uptimeify may mark a check as **inconclusive** rather than treating it as full downtime — so you don't get misleading "everything is down" alerts and incidents from a protection challenge rather than a real outage. ## Integrations ### Integrations URL: https://docs.uptimeify.io/integrations Description: Uptimeify delivers alerts to the tools you already use — chat, on-call, issue trackers and more — plus firewall allowlisting and a full REST API. Summary: ## Notification channels Deliver alerts to where your team already works. Channels are configured per customer and attached to your notification rules. - Manage in the app under the customer's **Notifications** settings. - Automate with the [Notification Channels API](/api/notification-channels) (create, list, update, delete, and **test** a channel). Every channel below is supported out of the box. ### Direct | Channel | Delivers via | You provide | |---------|--------------|-------------| | **Email** | E-mail | Recipient address(es); falls back to the customer/org email | | **SMS** | Text message | Phone number(s); falls back to the customer/org phone | | **Webhook** | Your HTTP endpoint | Endpoint URL (optional custom headers and JSON body template) | ### Chat & collaboration | Channel | You provide | |---------|-------------| | **Slack** | Incoming webhook URL (optional username, icon, color) | | **Microsoft Teams** | Incoming webhook URL | | **Discord** | Incoming webhook URL (optional username, color) | | **Telegram** | Bot token + chat ID | | **Google Chat** | Incoming webhook URL | | **Mattermost** | Incoming webhook URL | | **Rocket.Chat** | Incoming webhook URL | | **Matrix** | Homeserver URL + room ID + access token | | **Lark / Feishu** | Incoming webhook URL | | **DingTalk** | Incoming webhook URL (access token in the URL) | | **WeCom** | Incoming webhook URL (key in the URL) | ### On-call & incident response | Channel | You provide | |---------|-------------| | **PagerDuty** | Events API v2 routing key | | **Opsgenie** | API key + region (EU/US), optional priority | | **ilert** | Integration key | | **Grafana OnCall** | Incoming webhook URL | | **Squadcast** | Incoming webhook URL (token in the URL) | | **incident.io** | Alert source URL + bearer token | | **All Quiet** | Inbound webhook URL (the URL is the secret) | ### Push & lightweight | Channel | You provide | |---------|-------------| | **Pushover** | User key + API token | | **ntfy** | Topic URL (optional access token) | | **Gotify** | Server URL + app token | ### Issue trackers & ITSM | Channel | You provide | |---------|-------------| | **Jira** | Base URL + email + project key + issue type + API token | | **GitHub** | Repository + token (PAT); optional Enterprise API base URL | | **GitLab** | Project ID + token; optional self-hosted base URL | | **Linear** | Team ID + API key | | **ServiceNow** | Instance URL + username + password | ## Escalation policies Define multi-step, time-based escalation so an unacknowledged alert moves to the next responder automatically. - Configure and test via the [Escalation API](/api/escalation). ## Firewall allowlisting If your site sits behind a firewall or WAF, allowlist our monitoring nodes so checks aren't blocked. - See [Firewall allowlisting](/integrations/firewall) for the dashboard and `GET /api/ips` endpoint. - The full node list is published at [/ips.txt](https://uptimeify.io/ips.txt). Whitelisting other providers? See [Monitoring IP whitelists](https://uptimeify.io/compare/uptimerobot/probe-ips). ## API & automation Everything above — and the rest of the platform — is scriptable. - Start with the [API Documentation](/api). - Generate a token under your account and authenticate with `Authorization: Bearer wsm_`. ### Firewall allowlisting (Monitoring node IPs) URL: https://docs.uptimeify.io/integrations/firewall Description: If your website is protected by a firewall or WAF, you may need to allowlist our monitoring nodes so we can reach your endpoint reliably. Summary: ## Dashboard (UI) You can view the current IP allowlist in the dashboard sidebar under “IP Addresses”. ## API (Automation) To fetch the current list programmatically, use the authenticated endpoint: - `GET /api/ips` ### Authentication Use an API token generated in the dashboard. ```bash BASE_URL="https://uptimeify.io" TOKEN="wsm_" curl -H "Authorization: Bearer $TOKEN" "$BASE_URL/api/ips" ``` ### Response ```json { "ipv4": ["203.0.113.10"], "ipv6": ["2001:db8::10"], "locations": { "de-nbg": ["203.0.113.10"] }, "updated_at": "2026-01-01T00:00:00.000Z", "documentation": "https://uptimeify.io/docs/integrations/firewall" } ``` Notes: - The IP list can change over time. Don’t hard-code it permanently. - Prefer periodic syncing on your side (e.g. via a scheduled job). ## Maintenance ### Maintenance URL: https://docs.uptimeify.io/maintenance Description: Maintenance windows let you plan work (deployments, updates, migrations) without triggering noisy alerts. During an active window the affected target is treated as in maintenance — alerts are suppressed and, if the customer has a status page, the service is shown as Maintenance instead of Degraded. Summary: ## Create a maintenance window Go to **Dashboard → Maintenance** and create a new window. Read-only users can create, edit, reactivate, and delete maintenance windows for the customers they are assigned to. Global support accounts cannot modify maintenance windows. | Setting | Description | |---------|-------------| | **Target** | One or more: a **website**, a **service monitor** (ICMP / SMTP / SSH / FTP / IMAP-POP), a **DNS monitor**, a set of **tags**, or the entire **customer**. See [Apply to multiple monitors or by tag](#apply-to-multiple-monitors-or-by-tag). | | **Name** | A friendly label, e.g. "Weekly updates". | | **Description** | Optional notes shown in history. | | **Start / End** | The window's time range. Times are interpreted in your timezone. | | **Active** | Toggle to enable/disable the window without deleting it. | ## Apply to multiple monitors or by tag A single maintenance window can cover many monitors at once: **Multi-monitor select in the form** In the maintenance window form, open the **Target** selector and pick any combination of websites and service monitors. All selected monitors are added to the window; they must all belong to the same customer. **Bulk "Set maintenance" from monitor lists** On any monitor list page (e.g. *Dashboard → Web*, *Dashboard → Server*) you can select multiple rows using the checkboxes, then choose **Set maintenance** from the bulk-action toolbar. This creates a single maintenance window covering all selected monitors at once, pre-populating the form with those monitors as targets. **Dynamic by-tag windows** Instead of (or in addition to) selecting individual monitors, you can select one or more **tags**. A tag-based window covers every monitor that currently carries the tag — and it stays current automatically: - A monitor **tagged after** the window is created is automatically covered; no update needed. - **Removing a tag** from a monitor drops it from coverage immediately. **Org-wide scope:** When you select tags with *no* explicit monitors and no customer context, the window is **org-wide** — it covers all monitors across the entire organization that carry those tags, regardless of which customer they belong to. Creating or editing an org-wide tag window requires **admin or editor** role; readonly users will receive a permission error. Tag coverage is evaluated live by the monitoring worker at the moment each check result arrives, so there is no lag between tagging a monitor and it being protected by the window. ## One-time vs recurring A window is either **one-time** (default) or **recurring**. Recurring windows carry a recurrence pattern: | Field | Meaning | |-------|---------| | `frequency` | `daily`, `weekly`, or `monthly` | | `interval` | Repeat every *N* days/weeks/months (e.g. `2` = every other week) | | `daysOfWeek` | For weekly: which days (`0` = Sunday … `6` = Saturday) | | `dayOfMonth` | For monthly: day of month (`1`–`31`) | | `endRecurrenceDate` | Optional date when the recurrence stops | The **Start / End** times define the window's length within each occurrence. ## Effect on status pages If the target's customer has a status page: - A target with an **active maintenance window** (and no open incidents) is shown as **Maintenance**. - Maintenance windows can also appear in **Recent History** (controlled by the status page's *Show recent maintenance* toggle — see [Status Pages](/status-pages#recent-history)). Maintenance does not override real outages: if there is an **open incident** during a maintenance window, the service is shown as **Degraded**, not Maintenance. See [Incidents](/incidents). ## Troubleshooting ### Window does not show as "active" - Verify **Active** is enabled. - Confirm the current time is between **Start** and **End**. - Check the start/end times are correct for your timezone. - For recurring windows, confirm today matches the recurrence pattern (`frequency`, `daysOfWeek`… ## Monitoring ### Monitoring URL: https://docs.uptimeify.io/monitoring Description: Monitor the availability and performance of your websites and services. Summary: In this section you will find information about all monitor types and how to configure them. **Website & HTTP:** Uptime, Keyword, Response Time, Page Size, HTTPS Redirect, SSL **Network & Services:** ICMP, SMTP, IMAP/POP, SSH, FTP **DNS & Domain:** DNS, DNSBL, Domain Expiry **Advanced:** Heartbeat (Cron), Playwright (Synthetic Browser) For a full categorized overview see [Monitoring Types](/monitoring/monitoring-types). ## Getting started - Create your first monitor: [Set up an Uptime monitor](/monitoring/monitoring-types/uptime) - Overview of all available monitor types: [Monitoring Types](/monitoring/monitoring-types) ### Managed vs. Self-Service Monitors URL: https://docs.uptimeify.io/monitoring/managed-vs-self-service Description: Every monitor has an ownership class that controls who may edit it and who receives its alerts. Summary: Every monitor — website, DNS, ICMP, SMTP, SSH, FTP, IMAP/POP, domain expiry, and DNSBL — carries an **ownership class** (`managementType`) with one of two values: - **`managed`** (default) — the organization runs the monitor on the customer's behalf. It is **read-only in the customer portal**; customers request edits through the change-request flow. Alerts follow the organization's full escalation setup, including org-level integrations (webhooks, OpsGenie, org SMTP). - **`self_service`** — the customer owns the monitor. Customer users (including `readonly`-role portal logins) can **create, edit, and delete** their own self-service monitors, bounded by a package quota. Alerts go to the **customer's recipients only** — org-level integration channels are skipped. Existing monitors were classified `managed`, so nothing changed for them until you explicitly flip a monitor. ## Who can do what | Action | Customer portal user | Organization admin | |---|---|---| | View a monitor | ✓ (own customer scope) | ✓ | | Edit/delete a `self_service` monitor | ✓ (own monitors) | ✓ | | Edit/delete a `managed` monitor | ✗ — unless the customer has the `canEditManaged` exception | ✓ | | Create monitors | ✓ as `self_service`, if allowed and within quota | ✓ (any class) | | Change a monitor's class (`managed` ⇄ `self_service`) | ✗ — always organization-only | ✓ | | Request a change / request managed status | ✓ (change request) | approves/rejects | Customers can never grant themselves rights: a customer-scoped API caller's writes to permission fields are ignored server-side, and flipping the class of a monitor is rejected with `403` (`managementTypeOrgOnly`). ## Permissions and inheritance Self-service behavior is configured at two tiers with a *null-means-inherit* model: 1. **Package config** (`PATCH /api/package-configs/:packageType`) sets the defaults for every customer on the package: `allowSelfService` (default `false`) and `maxSelfServiceUrls` (default `0`), plus the channel-permission defaults `enableEmailAlerts`, `enableSmsAlerts`, `enableWebhookAlerts`, `enableIntegrationAlerts`, `enablePostRequestEscalation`. 2. **Customer overrides** (`POST`/`PATCH /api/customers`) can set the same fields per customer. `null` (or omitting the field) means *inherit from the package config*. The per-customer `canEditManaged` flag additionally allows a specific customer to edit `managed` monitors without owning them. Resolution is always: customer value → package default → platform default, and it fails closed (absence = least privilege). ## The self-service quota `maxSelfServiceUrls` bounds a customer's **total** number of `self_service` monitors **across all monitor types** — five self-service websites plus three self-service ICMP monitors count as eight. When the quota is reached, creating another self-service monitor (or flipping an existing monitor to `self_service`) fails with `403` (`selfServiceQuotaReached`). ## Change requests For `managed` monitors, the portal shows a **Request change** action instead of edit controls. A request has a `kind`: - `change` — free-text ask ("please raise the check interval"). - `request_managed` — the customer asks the organization to take over responsibility for a monitor. Accepting this request flips the monitor to `managed` automatically. Requests land in the organization's change-request inbox (**Dashboard → Change Requests**), where an org admin accepts or rejects them. Open requests are capped at 10 per customer. See the [Change Requests API](/api/change-requests) for the endpoints. ## What this means for alert delivery The ownership class drives escalation routing at the worker level: - `managed` — unchanged, full org escalation (org integrations + customer recipients per your escalation config). - `self_service` — notifications are delivered to the customer's own recipients only. Organization-level integration channels (channels not bound to a customer or monitor) are skipped, so your ops tooling isn't paged for… ### Monitoring Types URL: https://docs.uptimeify.io/monitoring/monitoring-types Description: Uptimeify supports a wide range of monitor types — from HTTP uptime, keyword, and SSL checks to DNS, network services, and synthetic browser flows. Pick the type that matches what you need to watch. Summary: ## Website & HTTP HTTP/HTTPS availability and status-code checks for your websites. Verify expected text is present (or absent) in the response body. Alert when a site responds slower than your threshold. Track the response payload size and catch unexpected bloat. Confirm HTTP correctly redirects to HTTPS (with HSTS). Catch expiring or invalid TLS certificates before they break trust. ## Network & Services Ping a host to check reachability and packet loss. Check that mail servers accept connections on the SMTP port. Monitor inbound mail retrieval services. Verify SSH endpoints are listening and reachable. Check that FTP servers respond on their configured port. ## DNS & Domain Watch A, AAAA, MX, TXT, CNAME and other records for changes. Detect when your IPs land on DNS blocklists. Get warned well before a domain registration lapses. ## Advanced Be alerted when a scheduled job stops checking in. Synthetic browser flows that test real user journeys. ### DNS Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/dns Description: The DNS Monitor checks DNS responses for a hostname (e.g. example.com) on a fixed interval. This helps you detect unexpected record changes (A/AAAA), missing MX records, or TXT changes (SPF/DMARC / domain verification). Summary: ## How it works - We resolve the selected **record types (RRTypes)** (e.g. `A`, `AAAA`, `MX`, `TXT`). - Optionally, we compare the resolved values against your **Expected Values**. - Depending on your trigger settings, we can create incidents/alerts for: - **Resolve Error** (e.g. `NXDOMAIN`, timeout) - **Mismatch** (resolved values differ from Expected Values) ## Configuration ### Basic settings - **Hostname**: Hostname only, without protocol or path (e.g. `example.com`, not `https://example.com/path`). - **Check interval**: How often to check (e.g. every 30 minutes). - **Status**: - `active`: checks run normally. - `maintenance`: checks still run, but alerting may be dampened depending on alert logic. - `disabled`: checks do not run. ### DNS checks - **RRTypes**: Comma-separated list, e.g. `A, AAAA, MX, TXT`. - **Match mode**: - `exact`: values must match exactly. - `contains`: expected values must be contained in the response. - **Expected values**: a list per RRType (one value per line). Empty fields mean “do not validate”. - **Triggers**: - `resolveError`: alert on DNS resolve errors. - `mismatch`: alert when Expected Values do not match. ## Monitoring locations DNS checks run from our monitoring locations. If a monitor does not specify its own restrictions, (if configured) the **customer-level allowed countries** apply. ### DNSBL Monitoring URL: https://docs.uptimeify.io/monitoring/monitoring-types/dnsbl Description: Monitor the reputation of your IP addresses on blocklists. Summary: **Status: Lab** This feature is currently in the **Lab phase**. This means we are still actively optimizing intervals and the selection of lists. DNSBL (DNS-based Blocklist) Monitoring regularly checks whether your server's IP address is listed on one of the known "Blacklists" (Blocklists/RBLs). Being listed on such a list often has serious consequences for email delivery (mails land in spam or are rejected). ## How it works We use our own open-source engine **[uptimeify-dnsbl](https://www.npmjs.com/package/uptimeify-dnsbl)** to check your IP address against over 50 international spam databases. ### Check Interval Currently, we perform the check **every 180 minutes (3 hours)**. - **Reason**: DNSBL operators often block excessive queries ("Rate Limiting"). A 3-hour rhythm is a good compromise between timeliness and "Good Citizenship" towards list operators. - *Note*: If there is a real need for more frequent checks, please contact us. ## What happens if a match is found? If we find your IP on a list (e.g., Spamhaus, Barracuda, SORBS): 1. **Notification**: You receive an alert via your configured channels. 2. **Details**: We show you the specific reason (e.g., "Listed in SBL" or "Dynamic IP Range"). 3. **Solution**: Where available, we provide a direct **Delisting Link** through which you can request removal from the list operator. ## Supported Lists We query a curated list of reliable providers. A complete overview can be found on the page [Used Lists](/monitoring/monitoring-types/dnsbl/lists). ### Used RBL Lists URL: https://docs.uptimeify.io/monitoring/monitoring-types/dnsbl/lists Description: We currently monitor your IP addresses against the following lists. This selection covers the most important and reliable international anti-spam databases. Summary: We use **[uptimeify-dnsbl](https://www.npmjs.com/package/uptimeify-dnsbl)** for this. ## Spamhaus Project *Probably the most important RBL worldwide.* - Spamhaus ## Other Important Lists - Barracuda (BRBL) - SpamCop - SORBS (Aggregate) - UCEPROTECT (Level 1, 2) - Hostkarma - Backscatterer - Invaluement SIP - SpamCannibal - DroneBL - Spam Eating Monkey (SEM-BLACK) - URIBL Black - RV-SOFT Technology - ZapBL - Suomispam Reputation - Kempt.net - Korea Services - NiX Spam - Passive Spam Block List (PSBL) - InterServer RBL - all.s5h.net - Abuse.ch (Combined, Drone, Spam) - 0spam (RBL, Blocklist) - Singular TTK PTE - SpamRats (Spam, Dyna, NoPtr) - Spamsources Fabel - Virus RBL JP - Woody's SMTP Blacklist - WPBL - Gweep (Proxy, Relays) - Digibase Spambot - Lashback UBL - WormRBL - Team Cymru Bogons - Nether.net Relays - Imp.ch Spam RBL - Mailspike Z - Anonmails.de - Pedantic.org - GBUdb Truncate ## Usage Notes We perform the queries in an "Aggregated" manner. This means we do not query each list individually one after the other, but parallelized and optimized to keep response time low and avoid timeouts. ### Domain Expiry Monitoring URL: https://docs.uptimeify.io/monitoring/monitoring-types/domain-expiry Description: An expired domain is one of the most severe incidents that can happen to a website. Once a domain expires, the entire online presence becomes unreachable — and in the worst case, the domain is registered by a third party. Our Domain Expiry Monitoring helps you proactively prevent this. Summary: ## How it works We use the **RDAP protocol** (Registration Data Access Protocol) — the modern successor to WHOIS — to query the registration data of your domains directly from the responsible registries. RDAP delivers structured, reliable data and is supported by all major TLDs. ### Check Interval Currently, we perform the check **every 12 hours** (configurable via environment variable). - **Reason**: Domain registration data changes infrequently. A 12-hour rhythm provides timely detection while remaining respectful towards registry rate limits. - *Note*: If there is a real need for more frequent checks, please contact us. ## Two monitoring paths Domain Expiry Monitoring works through two independent channels: ### 1. Website-based checks If the **Domain Expiry Check** is enabled for a website, we automatically extract the domain from the URL and check its expiry date. Results are stored alongside the regular monitoring data. ### 2. Registered customer domains Domains can also be registered independently in the **Admin → Domains** section. This is useful for: - Domains that are not actively monitored as websites (e.g., parked domains, mail-only domains). - Tracking domains with individual warning thresholds per domain. - Per-domain notification overrides (separate email/phone contacts). ## Thresholds Two configurable thresholds determine when alerts are triggered: | Threshold | Default | Purpose | |---|---|---| | **Warning** | 30 days | Early heads-up that renewal is due soon. | | **Critical** | 7 days | Urgent alert — domain expires within days. | These thresholds can be configured individually per website or per registered domain. ## What happens when a threshold is breached? 1. **Warning**: You receive an alert via your configured notification channels when the domain enters the warning window. 2. **Critical**: An urgent alert is triggered if the domain expires within the critical threshold. 3. **Expired**: If the domain has already expired, we flag it immediately. 4. **Recovery**: When a domain is renewed and no longer within the warning window, open incidents are automatically resolved and a recovery notification is sent. ## Monitored Data For each domain, we record and display: - **Expiry Date**: When the domain registration expires. - **Registrar**: Which registrar manages the domain (e.g., "INWX", "Hetzner", "GoDaddy"). - **Days Until Expiry**: Calculated in real time. - **Current Status**: OK, Warning, Critical, or Expired. - **Last Checked**: Timestamp of the most recent RDAP lookup. ## Supported TLDs RDAP is supported by all major gTLDs (.com, .net, .org, etc.) and many ccTLDs (.de, .at, .ch, .nl, .uk, etc.). If a TLD is not supported by RDAP, we skip the check silently — no false alerts are generated. ## Troubleshooting If we report a domain expiry issue: 1. Check with your registrar whether the domain is set to **auto-renew**. 2. Verify that the payment method on file with your registrar is still valid. 3. For domains managed by third parties, confirm that the responsible person is aware of the upcoming renewal. ### FTP Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/ftp Description: The FTP Monitor checks whether your FTP service is reachable and responsive. This helps detect outages on file transfer infrastructure used by legacy integrations, batch exports, or partner uploads. Summary: ## How it works - We connect to your FTP endpoint and verify that the service responds. - If the server cannot be reached or does not respond within the configured timeout, the check fails. ## Configuration ### Basic settings - **Hostname**: Hostname only, without protocol or path. - **Port**: Optional (default is typically 21). - **Check interval** and **Timeout**. - **Status**: `active`, `maintenance`, `disabled`. ### Advanced settings If your server requires authentication or encryption (e.g. FTPS), advanced options can be configured via the monitor settings. ### Monitoring locations FTP checks run from our monitoring locations. Monitor-level **Allowed Check Countries** (or customer-level defaults) control which locations are used. ### Heartbeat Monitoring (Cron) URL: https://docs.uptimeify.io/monitoring/monitoring-types/heartbeat Description: Heartbeat monitoring (also known as Cron Monitoring) works in reverse: instead of us checking your server, your server (or script) notifies us that it is alive. Summary: This is perfect for monitoring: - **Daily Backups:** Ensure your database backups actually ran. - **Background Jobs:** Monitor workers, import scripts, or periodic tasks. - **Intranet Devices:** Monitor devices behind a firewall that can send outbound requests. ## How it works 1. You create a **Heartbeat Monitor** in the dashboard. 2. We give you a unique **Heartbeat URL**. 3. You configure your script (Cronjob, Worker) to call this URL when it finishes successfully. 4. We expect a ping within your configured **Interval** (plus a **Grace Period**). 5. If we don't receive a ping in time, we send an alert: "Heartbeat missing". ## Configuration ### Expected Interval How often do you expect the ping? - *Example:* For a daily backup, set this to **24 hours** (1440 minutes). - *Example:* For a minutely worker, set this to **1 minute**. ### Grace Period How much delay is acceptable? - *Example:* If your backup usually takes 10 minutes but sometimes 30, set the Grace Period to **30 minutes**. - We will only alert if `Last Ping Time + Interval + Grace Period < NOW`. ## Usage Examples ### Linux Cronjob (Backup Script) ```bash #!/bin/bash # Run backup ... pg_dump dbname > backup.sql # If successful, ping the heartbeat if [ $? -eq 0 ]; then curl -m 10 --retry 3 https://ping.uptimeify.io/ping/YOUR_TOKEN fi ``` ### PowerShell (Windows) ```powershell # Run task... Write-Output "Task running..." # Ping Heartbeat Invoke-RestMethod -Uri "https://ping.uptimeify.io/ping/YOUR_TOKEN" ``` ### Node.js Worker ```javascript await doImport(); // Ping await fetch('https://ping.uptimeify.io/ping/YOUR_TOKEN'); ``` ### HTTPS Redirect Check URL: https://docs.uptimeify.io/monitoring/monitoring-types/https-redirect Description: Security and SEO are indispensable today. The HTTPS Redirect Check ensures that visitors accessing your website unencrypted via http:// are automatically redirected to the secure https:// version. Summary: ## Why is this important? - **Security**: Prevents Man-in-the-Middle attacks. - **SEO**: Search engines like Google prefer HTTPS and penalize sites without correct redirection. - **User Trust**: Users see the lock symbol in the browser. ## How it works This check is an option within the Uptime Monitor. When enabled: 1. We explicitly call the URL with `http://`. 2. We expect a status code `301` (Permanent Redirect) or `302` (Found) as well as `307/308`. 3. We check if the redirect target starts with `https://`. ## Configuration You can find this setting in the advanced options of your monitor: - **Enable HTTPS Redirect Check**: Enable this option to enforce the redirect. ### ICMP Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/icmp Description: The ICMP Monitor checks whether a host is reachable on the network. This is ideal for infrastructure components that do not expose HTTP endpoints (e.g. routers, firewalls, VPN gateways, databases, or internal services). Summary: ## How it works - We send ICMP echo requests (“ping”) to your **hostname**. - The monitor is considered healthy when the target responds within the configured timeout. - We record latency and detect sustained reachability problems. ## Configuration ### Basic settings - **Name**: A human-friendly label. - **Hostname**: Hostname or IP address (no protocol, no path). - **Check interval**: How often to check. - **Timeout**: How long to wait for a response. - **Status**: - `active`: checks run normally. - `maintenance`: checks still run, but alerting may be dampened depending on alert logic. - `disabled`: checks do not run. ### Monitoring locations ICMP checks run from our monitoring locations. - If you set **Allowed Check Countries** on the monitor, checks run only from matching locations. - If the monitor has no restrictions, (if configured) the **customer-level allowed countries** apply. ### IMAP/POP Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/imap-pop Description: The IMAP/POP Monitor verifies that your mail server is reachable for clients. This is useful for detecting authentication and connectivity issues that impact inbox access. Summary: ## How it works - We connect to your IMAP or POP endpoint and validate that the service responds. - If the server cannot be reached or does not respond in time, the check fails. ## Configuration ### Basic settings - **Hostname**: Hostname only, without protocol or path. - **Port**: Optional (commonly 143/993 for IMAP, 110/995 for POP). - **Check interval** and **Timeout**. - **Status**: `active`, `maintenance`, `disabled`. ### Advanced settings Protocol selection (IMAP vs POP) and other advanced options (e.g. encryption/auth requirements) can be configured via the monitor settings. ### Monitoring locations IMAP/POP checks run from our monitoring locations. You can restrict execution using **Allowed Check Countries** (monitor-level) or by using the customer-level defaults. ### Keyword Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/keyword Description: Sometimes a page is technically \\\"online\\\" (Status Code 200) but doesn't show the desired content – for example, a white page, a database error message, or \\\"Out of Stock\\\". The Keyword Monitor (also called \\\"Content Monitor\\\") solves this problem. Summary: ## How it works The Keyword Monitor downloads the HTML body of your page and searches it for a specific text (string). It is useful for ensuring that: - The database connection is working (check for dynamic content). - The CMS renders correctly. - No maintenance mode is displayed. ## Configuration Modes You can run the monitor in two modes: ### 1. "Must Contain" (Keyword Present) Alert if the word is **NOT** found. - **Use Case**: Check for "Welcome", "Imprint", or the company name in the footer. - **Example**: Check for the name of a bestseller product on a shop page. ### 2. "Must Not Contain" (Keyword Absent) Alert if the word **IS** found. - **Use Case**: Check for error messages. - **Examples**: "MySQL Error", "404 Not Found" (in text), "Hacked by", "Maintenance Mode". ## Setup Steps 1. Create a new monitor or edit an existing one. 2. Under "Advanced Settings", select the **Keyword Check** option. 3. Enter the search term (Case-sensitive!). 4. Save the monitor. ### Page Size Check URL: https://docs.uptimeify.io/monitoring/monitoring-types/page-size Description: The Page Size Check monitors the size of your website's HTML response content (body) in bytes. Unexpected changes in file size can indicate serious issues that are missed by a pure status code check (200 OK). Summary: ## Use Cases - **Hacks / Defacements**: Attackers often inject code, significantly increasing the page size. - **Empty Pages**: A database error could cause only the header to render (page suddenly very small), although the server reports Status 200. - **Performance**: Accidentally including huge scripts or CSS files in the HTML. ## Configuration You can define thresholds: ### Min Page Size Alert if the page is smaller than X bytes. - *Recommendation*: Set this to approx. 80-90% of your page's normal size to detect partially empty renderings. ### Max Page Size Alert if the page is larger than Y bytes. - *Recommendation*: Protects against "code bloat" or injections. The check is considered failed if the actual size is outside this range. ### Playwright Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/playwright Description: For critical processes like Login, Checkout, or Registration, a simple HTTP check is often insufficient. The Playwright Monitor loads your website in a real browser (Headless Chromium) and executes a script defined by you. Summary: This simulates a real user and uncovers JavaScript errors, broken buttons, or UI issues. ## How it works We execute your Playwright script in our secure cloud environment. - **Success**: The script runs to completion without errors. - **Error**: An `expect` check fails or a timeout occurs. We automatically save a **screenshot** and the error message. ## Example: Testing Login Here is a simple script to test a login process: ```javascript test('User can login', async ({ page }) => { // 1. Navigation await page.goto('https://app.example.com/login'); // 2. Fill form (Using Env Variables) await page.fill('input[name="email"]', 'monitor-user@example.com'); await page.fill('input[name="password"]', process.env.MONITOR_PASSWORD); // 3. Submit await page.click('button[type="submit"]'); // 4. Verification (Wait for dashboard element) await expect(page).toHaveURL(/dashboard/); await expect(page.locator('.welcome-message')).toContainText('Hello'); }); ``` ## Environment Variables (Secrets) You should never store passwords, API keys, or sensitive data directly in the script ("hardcoding"). Instead, use **Environment Variables**. ### Setup 1. Navigate to **Monitor Settings**. 2. Open the **Advanced Settings** section. 3. Find the **Environment Variables** section. 4. Enter the Key and Value. - Example Key: `PASSWORD` - Example Value: `SecretPassword123!` ### Usage in Script In Playwright code, access values via `process.env.KEY`. The values are injected into the secure worker environment only at runtime. ```javascript test('Secure Login', async ({ page }) => { await page.goto('https://example.com/login'); // Secure access via process.env await page.fill('#password', process.env.PASSWORD); await page.click('#submit'); }); ``` ### Security - Values are stored **encrypted** in our database. - They are not visible in plain text in the frontend editor after saving (depending on permissions). - They do not appear in the screenshot log (unless you explicitly `console.log` them). ## Tips for Stable Tests - Use `data-testid` attributes for selectors where possible. ### Response Time Check URL: https://docs.uptimeify.io/monitoring/monitoring-types/response-time Description: In addition to pure availability, speed is crucial for user experience. The Response Time Check measures how long your server takes to respond to a request. Summary: ## What is measured? We typically measure the **Time to First Byte (TTFB)** as well as the time for the complete transfer of the HTML document. ## Configuration You can set thresholds for warnings: - **Threshold (ms)**: If the response time exceeds this value (e.g., 2000ms), an alarm is triggered or the status is marked as "Degraded", depending on configuration. ## Analysis In the monitor details, you will find charts showing the development of response time over time. This helps you to: - Identify performance bottlenecks at specific times (e.g., during backups). - See the impact of code deployments on speed. ### SMTP Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/smtp Description: The SMTP Monitor verifies that your SMTP server is reachable and responsive. This helps you detect outages of outbound mail gateways and mail delivery infrastructure before users report missing emails. Summary: ## How it works - We connect to your SMTP server and validate that it responds as expected. - If the server cannot be reached or does not respond in time, we mark the check as failed. ## Configuration ### Basic settings - **Hostname**: Hostname only, without protocol or path. - **Port**: Optional. Use your SMTP port (commonly 25 / 587 / 465). - **Check interval** and **Timeout**. - **Status**: `active`, `maintenance`, `disabled`. ### Advanced settings Depending on your use case, advanced options (e.g. encryption/auth requirements) can be configured via the monitor settings. ### Monitoring locations SMTP checks run from our monitoring locations. You can restrict execution using **Allowed Check Countries** (monitor-level) or by using the customer-level defaults. ### SSH Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/ssh Description: The SSH Monitor checks whether your SSH service is reachable. It is commonly used to detect firewall issues, network outages, or server crashes affecting administrative access. Summary: ## How it works - We attempt to connect to your SSH service. - If the server cannot be reached, rejects connections unexpectedly, or times out, the check fails. ## Configuration ### Basic settings - **Hostname**: Hostname or IP address. - **Port**: Optional (default is typically 22). - **Check interval** and **Timeout**. - **Status**: `active`, `maintenance`, `disabled`. ### Monitoring locations SSH checks run from our monitoring locations. Use **Allowed Check Countries** to limit where checks run from. ### SSL Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/ssl Description: Expired SSL certificates are a common cause of downtime and loss of user trust. Browsers display warnings like \\\"Connection not secure\\\". Our SSL Monitor helps you proactively prevent this. Summary: ## How it works The SSL Monitor regularly checks the configuration of your TLS/SSL certificate. It is often integrated into the Uptime Monitor but can also be configured separately. ## Monitored Metrics ### 1. Expiration (Expiry) This is the most critical check. We alert you well before the expiration date so you can renew the certificate. - **Notification**: By default, we remind you **30, 14, 7, and 1 day(s)** before expiration (configurable). ### 2. Validity & Chain of Trust We check if the certificate: - Is signed by a trusted Root CA. - Has not been revoked (OCSP/CRL Check). - Is issued for the correct hostname (domain). ## Troubleshooting If we report an SSL error: 1. Check the expiration date. 2. Check if "Intermediate Certificates" are correctly installed (Chain incomplete error). 3. Ensure the hostname in the certificate (CN or SAN) matches the monitored URL. ### Uptime Monitor URL: https://docs.uptimeify.io/monitoring/monitoring-types/uptime Description: The Uptime Monitor is the core of your monitoring strategy. It regularly checks if your website or API endpoint is accessible to your customers. We recommend setting up at least one Uptime Monitor for every publicly accessible page. Summary: ## How it works We send HTTP or HTTPS requests to your URL at the interval you choose (e.g., every 30 seconds or every minute). We consider the monitor "Online" if: 1. The server responds (no timeout). 2. The **Status Code** matches expectations (default `2xx`, e.g., 200 OK). If an error is detected, we verify it from multiple locations worldwide to avoid false alarms before sending a notification. ## Create a website ### Where is this in the UI? In the dashboard, navigate to **Websites** and click **New website** / **Create website**. ### Name Choose a name that is easy to recognize for your team (e.g. "Marketing Website", "Shop API", "Customer Portal"). ### URL Uptimeify **automatically prepends `https://`** if you enter a plain hostname (e.g. `example.com`), so you don't need to type the protocol yourself — but you can always paste the full URL (e.g. `https://example.com`) as well. Tips: - Prefer the canonical target URL (usually `https://…`). - If you want to verify HTTP→HTTPS behavior, also use the **HTTPS Redirect** monitor type. ### Status You can keep a website active or temporarily disable it (e.g. during migrations). A disabled website is not monitored. ## Configuration ### Basic Settings - **URL**: The full address (e.g., `https://example.com`). - **Check Interval**: How often to check (e.g., 60s). ### Advanced Settings - **Expected Status Codes**: By default, we check for `200-299`. You can adjust this, e.g., to `200,301,302` if redirects should be considered a success. - **Timeout**: Maximum time to wait for a response (Default: 30s). - **HTTP Method**: Default is `GET`. You can also choose `HEAD`, `POST`, etc. - **Request Body & Headers**: Send JSON data or authentication tokens (e.g., `Authorization: Bearer ...`). ## Optional checks When configuring an Uptime Monitor, you can enable additional checks alongside the basic availability test: - **SSL**: Monitor certificate validity and expiration date → see [SSL Monitor](/monitoring/monitoring-types/ssl) - **Response Time**: Set performance thresholds and get alerted when your site slows down (see [Response Time](#response-time) below) - **Keyword / Content Validation**: Verify that specific content is present in the response body - **Page Size**: Alert on unexpected size changes that may indicate missing resources or bloat ## Common pitfalls ### URL vs. hostname (DNS/ICMP) The Uptime Monitor accepts a plain hostname (Uptimeify adds `https://` automatically) or a full URL. Some other monitor types work with a **hostname without protocol** and do not perform HTTP requests. - DNS Monitor: hostname without protocol (e.g. `example.com`) → see [DNS Monitor](/monitoring/monitoring-types/dns) - ICMP Monitor: hostname without protocol (e.g. `server.example.com`) → see [ICMP Monitor](/monitoring/monitoring-types/icmp) ### Authentication / bot protection If your site uses Basic Auth, token auth, or bot protection, a simple HTTP check may fail. - Configure auth headers or Basic Auth credentials in the **Request Headers** field. - For complex login flows, **Playwright** monitors are often the more robust choice. ## Response Time In addition to status, we also record the response time (Time to First Byte + Download). - You can configure alerts if the response time exceeds a threshold (e.g., > 2000ms), even if the status is 200 OK. ## Next steps - Investigate outages and view history: [Incidents](/incidents) ### Using Tags URL: https://docs.uptimeify.io/monitoring/tags Description: Organize and filter monitors with color-coded tags across all monitor types. Summary: Tags let you label any monitor — website, DNS, ICMP, SMTP, SSH, FTP, or IMAP/POP — with one or more color-coded badges. You can then filter every monitor list by tag and instantly see which monitors belong to a group (e.g. "Production", "Client A", "Staging"). ## Creating Tags Open **Settings → Tags** and click **New Tag**. Provide: - **Name** — a short label, up to 50 characters. - **Color** — choose from the fixed palette: `slate`, `red`, `amber`, `green`, `teal`, `blue`, `indigo`, `violet`, `pink`, or `gray`. Tags are organization-scoped: every member with sufficient permissions can see and use them. ### Readonly member rule Readonly members **can** create tags, but those tags are visible only to themselves. A readonly member cannot see, update, or delete tags created by other users. They can assign their own tags to any monitor they have read access to. ## Color Palette | Key | Color | |-----|-------| | `slate` | Slate / neutral gray | | `red` | Red | | `amber` | Amber / orange | | `green` | Green | | `teal` | Teal | | `blue` | Blue | | `indigo` | Indigo | | `violet` | Violet / purple | | `pink` | Pink | | `gray` | Gray | ## Assigning Tags Tags can be assigned in two places: ### From the monitor list (inline) In any monitor list (Websites, DNS, ICMP, etc.) find the **Tags** column. Click the tag chip area on a row to open the tag picker and toggle tags on or off for that monitor. ### From the monitor detail page Open a monitor's detail page and locate the **Tags** section. Use the tag picker to add or remove tags. Changes are saved immediately. ## The Tags Column The Tags column is visible by default in every monitor list. To get a more compact view, toggle the column off using the **Columns** menu at the top of the list. Your preference is saved per list. ## Filtering by Tag At the top of any monitor list, open the **Filter** menu and select one or more tags. The list narrows to show only monitors that carry **all** of the selected tags (AND logic). To clear the filter, deselect all tags or click **Reset filters**. ## Managing Tags Go to **Settings → Tags** to see the full tag list. From there you can: - **Edit** a tag's name or color (owner or admin only). - **Delete** a tag — this removes the tag from every monitor it was assigned to (cascade delete). ## API Reference See the [Tags API](../api/tags) for programmatic access to create, update, delete, and assign tags. ## Status Pages ### Status Pages URL: https://docs.uptimeify.io/status-pages Description: Status pages let you communicate service health to your customers transparently — live overall state, a per-service breakdown, and a short history of recent incidents and maintenance. Each page is fully brandable and can run on your own domain (e.g. status.example.com). Summary: 8 layouts, color schemes, accent color, custom title, and toggles for what to show. Serve a page on `status.example.com` with DNS verification and automatic HTTPS. Create, update, design, and manage domains programmatically. ## What a status page shows - **Overall state** — a single banner: Operational, Degraded, or Maintenance. - **Services** — the customer's monitored websites and service monitors, each with its own state. - **Uptime statistics** — optional per-service uptime percentages. - **Recent history** — optional list of recent incidents and maintenance windows. ### How the public state is derived Uptimeify computes each service's public state from two live signals — it never exposes raw check data: | Condition | Public state | |-----------|--------------| | One or more **open incidents** | **Degraded** | | **Active maintenance window** and no open incidents | **Maintenance** | | Neither | **Operational** | The overall banner reflects the worst state across all services. See [Incidents](/incidents) and [Maintenance](/maintenance) for how those signals are produced. ## Create a status page In the app, go to **Dashboard → Status Pages → Create**. A page always belongs to exactly one **customer** — it shows that customer's services. | Setting | Description | |---------|-------------| | **Customer** | Required. The customer whose services the page displays. | | **Public name** | The page title shown to visitors. | | **Slug** | Used for the friendly URL. Auto-generated from the name; lowercase letters, numbers, and hyphens. | | **Description** | Optional intro text shown under the title. | | **Visibility** | `public` (anyone can view) or `customer_members_only` (login + access to the customer required). | | **Published** | Toggle off to hide the page without deleting it. | You can do all of this via the [API](/api/status-pages/create-status-page) too. ## URLs Every status page is reachable at: - `/status/` — friendly URL based on the configured slug. - `/status/` — stable URL based on the page ID (always available, even if the slug changes). With a [custom domain](/status-pages/custom-domains) configured and active, the page is also served at the apex of that hostname, e.g. `https://status.example.com/`. ## Visibility & publishing - **`public`** — the page is reachable by anyone with the link. Best for customer-facing status. - **`customer_members_only`** — visitors must be logged in and have access to the customer. Best for internal or NDA-bound services. - **Published** is independent of visibility: an unpublished page returns *not found* regardless of visibility, which is useful while you are still setting it up. ## Recent history The **Recent History** section is controlled by two independent toggles: - **Show recent incidents** - **Show recent maintenance** These only affect the *history list*. Live indicators (such as a service currently being in maintenance) are always shown, independent of these flags. The [design settings](/status-pages/design) additionally control the history time window (`historyDays`). ## Troubleshooting ### "Status page not found" - Confirm the page is **Published**. - If visibility is `customer_members_only`, you must be logged in and have access to that customer. - Double-check the slug — it is normalized to lowercase-with-hyphens on save. ### A service shows the wrong state - **Stuck on Degraded?** There is still an open incident for that service — resolve it or wait for automatic recovery (see [Incidents](/incidents)). - **Expected Maintenance but see Operational?** Verify the maintenance window is **active** and the current time is within its start/end (see [Maintenance](/maintenance)). ### Custom Domains URL: https://docs.uptimeify.io/status-pages/custom-domains Description: Connect a hostname like status.example.com to a status page so it runs entirely under your own brand. A hostname can be bound to exactly one status page, and the certificate is issued automatically once the domain is verified and active. Summary: ## How it works A custom domain moves through three states: 1. **Pending** — added, waiting for DNS verification. 2. **Verified** — the TXT record was found; ready to activate. 3. **Active** — the page is served on the hostname over HTTPS. ``` Add hostname → Add TXT record → Verify → Activate → Point CNAME (pending) (your DNS) (verified) (active) (traffic) ``` ## Step 1 — Add the hostname In the app: **Dashboard → Status Pages → (page) → Custom Domain → Add**, enter `status.example.com`. Via the API: [Add Custom Domain](/api/status-pages/add-status-page-domain). Uptimeify returns a TXT verification record: - **TXT name**: `_uptimeify-verify.status.example.com` - **TXT value**: the token shown in the app / API response ## Step 2 — Add the TXT record Create the TXT record in your DNS provider exactly as shown. Keep it in place — it is also re-checked over time. DNS changes can take anywhere from a few minutes to a few hours to propagate. If verification fails immediately, wait and retry. ## Step 3 — Verify Click **Verify** (or call [Verify Status Page Domain](/api/status-pages/verify-status-page-domain)). Uptimeify looks up the TXT record and checks the token matches. On success the domain becomes **Verified**. ## Step 4 — Activate Click **Activate** (or call [Activate Status Page Domain](/api/status-pages/activate-status-page-domain)). The domain becomes **Active** and a TLS certificate is provisioned automatically (on-demand HTTPS) — no certificate upload required. ## Step 5 — Point traffic to Uptimeify Finally, point the hostname at Uptimeify so visitors actually reach the page — add the CNAME shown in the app for `status.example.com`. Once DNS resolves, `https://status.example.com/` serves your status page. Keep both records in place: the **TXT** record (used for ongoing verification) and the **CNAME** (routes visitor traffic). Removing the TXT record can cause the domain to fail re-verification. ## Removing a domain Remove the binding in the app or via [Remove Custom Domain](/api/status-pages/remove-status-page-domain). The status page stays reachable on its `/status/` and `/status/` URLs. ## Troubleshooting ### "TXT verification failed (token not found)" - Confirm the TXT **name** is exactly `_uptimeify-verify.`. - Confirm the TXT **value** matches the token from Uptimeify (no extra quotes or spaces). - Give DNS more time to propagate, then verify again. - Check you didn't add the record to the wrong zone (e.g. apex vs subdomain). ### The page doesn't load on my domain - Make sure the domain is **Active**, not just Verified. - Confirm the **CNAME** points to the target shown in the app. - The first request after activation may be slightly slower while the certificate is issued. ### Design & Branding URL: https://docs.uptimeify.io/status-pages/design Description: Every status page has a visual design configuration. Edit it in the app under Dashboard → Status Pages → (page) → Design, or via the design API. Changes are merged — you only send the fields you want to change, and the rest keep their current values. Summary: ## Layouts Choose one of eight layout presets. They all show the same data (overall state, services, optional stats and history) but differ in structure and density — preview each one live in the design editor. | Layout | Best for | |--------|----------| | `classic` | The default. A prominent hero banner with the overall state, followed by the service list. | | `cards` | Each service rendered as a card in a responsive grid. | | `minimal` | Stripped-back, text-first presentation with minimal chrome. | | `sleek` | A modern hero banner with an accent-color gradient. | | `board` | A dashboard-style board to see many services at a glance. | | `split` | A full-width header with a two-column body (status next to history). | | `timeline` | Emphasizes a chronological timeline of incidents and maintenance. | | `compact` | Dense layout that fits many services into little vertical space. | ## Appearance | Option | Values | Default | Description | |--------|--------|---------|-------------| | `colorScheme` | `light`, `dark`, `auto` | `auto` | `auto` follows the visitor's system preference. | | `accentColor` | hex color `#rrggbb` | `#6366f1` | Used for highlights, links, and gradients. | | `headerStyle` | `simple`, `centered`, `hero` | `simple` | How prominent the page header is. | | `fontFamily` | `system`, `mono` | `system` | `mono` gives a technical, monospaced look. | | `cardRadius` | `none`, `md`, `xl` | `md` | Corner rounding of cards and panels. | | `pageWidth` | `sm`, `md`, `lg`, `xl` | `lg` | Maximum content width. | ## Content & sections | Option | Type | Default | Description | |--------|------|---------|-------------| | `customTitle` | string (≤120) | — | Overrides the page title in the header. | | `customSubtitle` | string (≤200) | — | A subtitle shown under the title. | | `showUptimeStats` | boolean | `true` | Show per-service uptime percentages. | | `showServiceUrls` | boolean | `false` | Show each service's URL next to its name. | | `showLastChecked` | boolean | `false` | Show the "last checked" timestamp per service. | | `showHistory` | boolean | `true` | Show the recent history section. | | `historyDays` | number | — | How many days of history to include (bounded by the platform min/max). | | `showPoweredBy` | boolean | `true` | Show the "powered by Uptimeify" footer. Turn off for full white-labeling. | `showHistory` controls whether the history *section* is rendered. The separate **Show recent incidents** and **Show recent maintenance** toggles (on the page's main settings) control *what* goes into that section. See [Recent history](/status-pages#recent-history). ## Example (API) ```bash curl -X PATCH "$BASE_URL/api/status-pages//design" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "layout": "sleek", "colorScheme": "dark", "accentColor": "#10b981", "showServiceUrls": true, "showPoweredBy": false }' ``` Only the fields you send are changed; everything else keeps its current value. See [Update Status Page Design](/api/status-pages/update-status-page-design) for the full reference. ## White-labeling For a fully branded page with no Uptimeify references: 1. Set `showPoweredBy` to `false`. 2. Configure a [custom domain](/status-pages/custom-domains) so the page runs on your hostname. 3. Set an `accentColor` (and optionally `customTitle`/`customSubtitle`) that matches your brand.