# Onboarding Client Sites Without the Overhead: Provisioning via API

> Provision new client sites in minutes via REST API and custom fields instead of setting them up by hand: how agencies automate onboarding.

Source: https://uptimeify.io/blog/onboarding-client-sites-via-api

Every agency knows the moment: a new client signs, and before any monitoring runs, you click through forms: create the client, assign a package, add the site, configure monitors, fill in internal notes. For one client it's tedious. For twenty it's half a workday. **Provisioning via API turns that click path into a script that runs in seconds.** New client sites get set up in minutes instead of by hand. This article walks through the exact sequence, the role of custom fields, and how to automate an entire onboarding.

- **Two calls cover the core:** `POST /api/customers` creates the client, `POST /api/websites` adds the first site with monitoring.
- **Custom fields** attach your internal metadata (reference number, team, environment) right at creation, no cleanup afterward.
- **Bulk onboarding:** iterate over a CSV and provision an entire client base in one pass (up to 600 requests/minute).
- **Secure per client:** client-scoped `wsm_` tokens limit access to exactly one client.
- **No developer needed to start.** Each call is a single cURL command.

## The problem: manual onboarding doesn't scale

Setting up one client by hand is harmless in isolation, a few forms, a few minutes. The problem is repetition. Every step is error-prone (a forgotten field, a wrong URL, a missed monitor), every step is unproductive time, and the total grows linearly with your client count. At exactly the moment your agency grows, onboarding becomes the bottleneck.

Then there's inconsistency. Set things up by hand and you do it slightly differently every time, sometimes the reference number is filled in, sometimes not; sometimes the monitor is "DNS Acme," sometimes "acme dns check." Those little messes come back to bite you later, in reports, filters, and handovers. Automation solves both problems at once: it costs next to no time per client, and it creates every client from the exact same blueprint.

Manual onboarding scales linearly with client count and breeds inconsistency. A provisioning script costs almost nothing per client and creates every client identically.

## The basics: a bearer token and one REST call

Before the actual sequence, the foundation. The Uptimeify API is a classic REST interface: you send JSON to an endpoint, you get JSON back. Authentication runs through a bearer token you generate in the dashboard under Settings → API. Every token starts with `wsm_`. Miss that prefix and the API replies with `401 Unauthorized`.

In its simplest form, a call looks like this:

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

curl -H "Authorization: Bearer $TOKEN" "$BASE_URL/api/customers"
```

That's all the groundwork you need to start. If you've ever written a shell script, you've got everything to automate onboarding, no SDK, no framework, no build pipeline. One detail is worth knowing upfront: tokens can be issued **organization-wide** or **client-scoped**. For provisioning scripts that need to create any client, use an organization-wide token; for an integration meant to touch only a single client, use a client-scoped one. Anything outside the scope is rejected with `403 Forbidden`.

## The provisioning sequence in two calls

The heart of onboarding is two calls. The first creates the client, the second creates the first site, and links them through the returned ID.

**Step 1: Create the client.** A `POST` to `/api/customers` creates the client. The package and any custom fields ride along in the same request:

```bash
curl -X POST "$BASE_URL/api/customers" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Ltd",
    "email": "ops@deinkunde.com",
    "packageType": "business",
    "customFields": {
      "internalReference": "KD-999",
      "region": "EU"
    }
  }'
```

The response returns the new client ID, both as an internal `id` and as a `publicId` (UUID). That ID is the thread everything else hangs from.

**Step 2: Attach the first site.** Using the `customerId` from step 1, a `POST` to `/api/websites` creates the first site to monitor:

```bash
curl -X POST "$BASE_URL/api/websites" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": 123,
    "name": "Acme Marketing Site",
    "url": "https://deinkunde.com"
  }'
```

Important: the `url` must include the protocol (`https://…`). From that moment the site is monitored from multiple EU locations, every outage confirmed before an alert fires. Two calls, and the client is in monitoring. What was a multi-minute click path in the interface is now a script fragment that runs in under a second.

The core is a chain of two calls: create the client (`/api/customers`), keep the ID, attach the site (`/api/websites`). The returned `customerId` is the thread every further monitor hangs from.

## Adding more monitors: DNS, ping, SSL & co.

Plain uptime monitoring of the website is often just the start. For a complete monitoring baseline, you attach further monitors with the same `customerId`. Each type has its own endpoint. A DNS monitor, for instance:

```bash
curl -X POST "$BASE_URL/api/dns-monitors" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": 123,
    "name": "DNS: deinkunde.com",
    "hostname": "deinkunde.com",
    "dnsConfig": {
      "rrtypes": ["A"],
      "matchMode": "exact",
      "expectedValues": { "A": ["93.184.216.34"] }
    }
  }'
```

ICMP (ping), SMTP, SSH, FTP and IMAP/POP follow the same pattern, each with `customerId`, `name`, and its type-specific fields. That turns the provisioning sequence into a template: a script that creates a defined baseline set of monitors per client, identical every time. One tip from practice: use consistent name prefixes (`DNS:`, `Ping:`, `SMTP:`) so reports and filters land cleanly later.

For provisioning to land cleanly, you need a structure where every client has its own clearly separated home. See how client management provides that structure.

## Custom fields: your internal structure from second one

The difference between "created somehow" and "filed cleanly into the system" is custom fields. They attach your own metadata to a client or a site: the internal reference number, the team in charge, the environment (production, staging), the region. They come in three flavors: a free text field, a select field, and a multi-select field.

You define the field definitions once via `/api/custom-fields`:

```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
  }'
```

After that you fill them, as seen above, directly in the `customFields` object when creating the client. The effect: every client provisioned by script is fully tagged from the first second. No "I'll fill that in later" sticky notes, no half-maintained records. Here, automation enforces the tidiness that manual setup constantly undermines.

Custom fields (text, select, multi-select) are defined once and then filled on every provisioning run. That files every new client correctly into your internal structures from the start, with no manual cleanup.

## From one-off to bulk onboarding

The API's full leverage only shows up at volume. Once the provisioning sequence exists as a script, the jump from one client to a hundred is just a loop. You keep your clients in a list, say a CSV of name, email, and URL, and call the same sequence per row:

```bash
while IFS=, read -r name email url; do
  # 1) create client, read customerId from the response
  # 2) attach site with that customerId
  # 3) add baseline monitors
done < clients.csv
```

Because the API allows up to 600 requests per minute, even larger migrations run in a single pass. This is where automation pays off most visibly: an existing client base that used to sit outside monitoring moves in all at once, without anyone filling in the same forms a hundred times. A project you'd otherwise put off for weeks becomes a script run of a few minutes.

## The real payoff: onboarding as a solved problem

At its core, provisioning via API isn't a technical flourish. It's the decision to solve a recurring problem exactly once. You write the sequence a single time, client, site, monitors, custom fields, and after that every further onboarding is just a call to that finished routine. The effort per new client drops from minutes to near zero, and the "human clicks a form" error source disappears entirely.

For your agency's technical track, that means two things. First, onboarding goes from bottleneck to non-issue. It no longer scales with your client count. Second, every client is created consistently, tagged cleanly, and fully monitored from the first moment. That's the invisible foundation that reliable reports, handovers, and automations can finally build on.

The click path was never the work your client pays you for. The API takes it off your hands, and gives you back the time for what does matter.

And if you would rather ask than script: the same surface is reachable from an AI assistant. The [Prompt Library](/resources/success-kit/prompt-library) collects twenty ready-to-run prompts for the checks and client reports that follow onboarding, ten of them without an account.

Automate your onboarding and make the click path a solved problem. See how Uptimeify's client management keeps provisioned clients cleanly separated and easy to navigate.
