Uptimeify Docs
Customers

Bulk Actions

Applies one action to many customers at once, for multi-select workflows.

POST /api/customers/bulk

Applies a single action to a list of customer ids. Each id is processed independently: one conflicting or missing customer does not abort the rest. The response is always 200 OK, even when some ids failed, so check failed rather than relying on the HTTP status alone.

Authentication

BASE_URL="https://uptimeify.io"
TOKEN="<your-api-token>"

Request Body

{
  "ids": [101, 102, 103],
  "action": "reports",
  "payload": {
    "enabled": true
  }
}
FieldTypeRequiredDescription
idsnumber[]yesCustomer ids (the numeric id, not publicId). Non-empty, at most 200 entries, positive integers, no duplicates.
actionstringyesOne of reports, activate, deactivate, delete, package.
payloadobjectdepends on actionRequired for reports and package (see below). Ignored for activate, deactivate, delete.

Actions

ActionEffectpayload
reportsSets monthlyReportsEnabled on each customer.{ "enabled": boolean } (required)
activateSets the customer's status to active (a no-op if already active) and cascades monitor statuses accordingly.none
deactivateSets the customer's status to inactive (a no-op if already inactive) and cascades monitor statuses accordingly.none
deleteHard-deletes the customer. Monitors and check history are removed with it via cascade. Not reversible.none
packageReassigns the customer to a different package by id.{ "packageId": number } (required)

package only accepts a numeric packageId that belongs to the target customer's own organization. For every caller except a global admin that is the same thing as your own organization, because you can only address customers inside it. A global admin addressing customers across organizations needs a packageId from each customer's own organization; one belonging to a different organization is rejected with invalidPackageType. Unlike Update Customer, it does not resolve a legacy packageType string or display name, since guessing which package was meant across up to 200 rows at once is not something the bulk endpoint does; look up the id from List Package Configs first.

payload.enabled and payload.packageId are validated once, up front, before any customer is touched. A malformed payload fails the whole request with 400 invalidRequestBody; it never turns into 200 identical per-id failures.

Example Request

curl -X POST "$BASE_URL/api/customers/bulk" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": [101, 102, 103],
    "action": "reports",
    "payload": { "enabled": true }
  }'

Example Response (partial result)

{
  "ok": [101, 103],
  "failed": [
    { "id": 102, "reason": "customerNotFound" }
  ]
}

ok lists the ids that were updated. failed lists the ids that were not, each with a reason string. Render the split (for example "2 of 3 updated"), never a blanket success from the fact that the request itself returned 200.

Common Errors

These fail the whole request before any customer is touched:

  • 401 unauthorized you are not logged in
  • 403 forbidden your role is readonly, or you are a global-supporter (both are read-only for this endpoint)
  • 400 invalidRequestBody ids is missing/empty/not an array, contains more than 200 entries, contains a non-integer, a value <= 0, or a duplicate; action is not one of the five supported actions; or payload.enabled / payload.packageId is missing or the wrong type for the chosen action

These appear per id, inside failed[].reason, without failing the request:

ReasonMeaning
customerNotFoundThe id does not exist, or belongs to another organization (global admins may address any id; everyone else is scoped to their own organization). Deliberately indistinguishable from "does not exist", so a caller cannot use this endpoint to probe which ids exist elsewhere.
invalidPackageTypepackage action only: payload.packageId does not resolve to a package config owned by this customer's organization.
organizationIdRequiredThe caller's session has neither an organization nor global-admin scope. Only possible for a malformed session/token; a normally authenticated caller never sees this.
unknownAny other rejection, most commonly a customer-scoped caller (a restricted role, or a customer-scoped API/agent token) addressing an id outside their assigned customers. Also the fallback for any error that carries no stable data.code.

On this page