---
title: "Create FTP Monitor"
description: "Creates a new FTP monitor."
---

`POST /api/ftp-monitors`

## Authentication

This endpoint requires an API token:

`Authorization: Bearer <token>`

## 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)
- `checkMode` (optional, string): `protocol` | `tcp`. Defaults to `protocol`.
  - In `tcp` mode the monitor performs a bare TCP port-reachability check: `ftpConfig` is not required and is not stored. In `protocol` mode the full FTP login check runs (existing behavior).
- `ftpConfig` (optional, object): FTP connection options (stored as JSON)
  - Required (`user` + `password`) unless `checkMode` is `tcp`.

### `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="<your-api-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

