---
title: "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."
---

`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,
  "monthlyReportsDefault": 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.

### `alertConsecutiveChecks`

An integer between **1 and 10** (values outside that range are rejected with `400` and
`data.code` `invalidRequestBody`). It is the number of consecutive failing cycles required before
an incident opens, and it also bounds how many consecutive successful cycles are required before
one closes. A very large value therefore does not just delay alerting, it delays recovery: at a
5-minute cadence a value of 999 would keep an incident open for 83 hours of uninterrupted green
checks. The cap matches the one the dashboard has always enforced.

### `monthlyReportsDefault`

`monthlyReportsDefault` (boolean, default `true`) is a **template**, not a live switch: it seeds a new customer's `monthlyReportsEnabled` at creation time. It never rewrites an existing customer, whose own value always wins once set. To push a changed default onto customers **already** on this package, call [Apply Report Default](/api/organization/apply-report-default) afterwards.

## Example (cURL)

```bash
BASE_URL="https://uptimeify.io"
TOKEN="<your-api-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,
    "monthlyReportsDefault":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,
  "monthlyReportsDefault": 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
- `400` with `data.code` `invalidRequestBody` when `alertConsecutiveChecks` is outside 1-10
- `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).

