Glossary
- Client
- The tenant account that owns users, entitlement, and billing. Your user belongs to one client.
- Workspace
-
A container inside a client for checks, domains, notification groups, and maintenance.
Most resource routes require
X-Workspace-Idfor a workspace you can see. - Uptime check
- An HTTP(S) or ping monitor. Frequency is one of 1, 2, 5, 10, or 15 minutes. Failures need a quorum of locations before an incident opens.
- Run
-
One monitoring cycle for a check. Aggregate state is
UP,DOWN, orUNKNOWNwhen locations disagree or do not finish in time. - Incident
-
An outage record for a check. Status is
open,acknowledged, orresolved. Severity ismajororcritical. - Domain
- A certificate-monitored hostname, separate from an uptime check.
- Notification group
- Alert routing: email, SMS, HTTPS webhook, Slack incoming webhook, and/or Android push. Attach groups to checks and domains.
- Maintenance window
- A one-time time range (workspace or single check) that suppresses incident creation and notifications. Recurring windows are not supported.
- Entitlement
-
Resolved trial / paid / expired access for the client. Mutations on monitoring resources
return
402 ENTITLEMENT_REQUIREDwhen the account is not entitled.
Base URL & conventions
- Production base:
https://geeksuptime.com - All routes below are under
/app/api/v1/ - JSON request bodies use
Content-Type: application/json - There is no long-lived API key or bearer token today — use HTTP Basic
- CSV export routes return
text/csv, not the JSON envelope - Creates typically respond with HTTP
201; other successes use200
Authentication
Send Authorization: Basic base64(email:password) on every protected call.
Prefer GET /app/api/v1/mobile/auth/me as the client bootstrap: it returns the
profile, permission flags, visible workspaces, a suggested current_workspace_id,
and entitlement.
Almost every resource route also requires
X-Workspace-Id: <id> for a workspace the user can see.
Missing or invalid → 400; inaccessible → 403.
The legacy POST /app/api/v1/authenticate endpoint accepts
{ "email_address", "password" } and returns a raw user object (password stripped)
or an empty array. Prefer /mobile/auth/me for new integrations.
curl -sS -u '[email protected]:your-password' \
'https://geeksuptime.com/app/api/v1/mobile/auth/me'
<?php
$email = '[email protected]';
$password = 'your-password';
$base = 'https://geeksuptime.com';
$ch = curl_init($base . '/app/api/v1/mobile/auth/me');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => $email . ':' . $password,
CURLOPT_HTTPHEADER => ['Accept: application/json'],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$json = json_decode((string) $body, true);
if ($status !== 200 || empty($json['success'])) {
throw new RuntimeException($json['error']['message'] ?? 'auth/me failed');
}
$workspaceId = (int) ($json['data']['current_workspace_id'] ?? 0);
echo "Workspace: {$workspaceId}\n";
const email = '[email protected]';
const password = 'your-password';
const base = 'https://geeksuptime.com';
const basic = btoa(`${email}:${password}`);
const res = await fetch(`${base}/app/api/v1/mobile/auth/me`, {
headers: {
Authorization: `Basic ${basic}`,
Accept: 'application/json',
},
});
const json = await res.json();
if (!res.ok || !json.success) {
throw new Error(json.error?.message ?? 'auth/me failed');
}
const workspaceId = json.data.current_workspace_id;
console.log('Workspace', workspaceId);
Typical success payload (fields abbreviated):
{
"success": true,
"data": {
"user": {
"id": 15,
"email_address": "[email protected]",
"flag_is_admin": 1,
"permissions": { "…": true },
"subscription_plan": "growth"
},
"workspaces": [
{ "id": 7, "name": "Production", "description": null }
],
"current_workspace_id": 7,
"entitlement": { "…": "trial or paid summary" }
}
}
Response envelope
Protected mobile routes return one of:
{
"success": true,
"data": [ /* … */ ],
"pagination": { "limit": 50, "offset": 0, "total": 12 }
}
{
"success": false,
"error": {
"code": "ENTITLEMENT_REQUIRED",
"message": "An active trial or paid plan is required."
}
}
| HTTP | Code | When |
|---|---|---|
| 400 | BAD_REQUEST |
Missing workspace header, bad JSON, or invalid filters |
| 401 | UNAUTHORIZED |
Missing or wrong Basic credentials |
| 402 | ENTITLEMENT_REQUIRED |
Trial/paid access required for a mutating call |
| 403 | FORBIDDEN |
Permission, workspace, or plan limit denied the action |
| 404 | NOT_FOUND |
Resource id not found for this client |
| 405 | METHOD_NOT_ALLOWED |
Wrong HTTP method for the route |
| 409 | CONFLICT |
Duplicate name or conflicting state |
Examples
List down checks
Query params: limit (1–200), offset,
status=all|up|down|unknown|paused, optional search,
paused, favorite.
curl -sS -u '[email protected]:your-password' \
-H 'X-Workspace-Id: 7' \
'https://geeksuptime.com/app/api/v1/mobile/uptime-checks?limit=50&offset=0&status=down'
<?php
$email = '[email protected]';
$password = 'your-password';
$workspaceId = 7;
$base = 'https://geeksuptime.com';
$query = http_build_query([
'limit' => 50,
'offset' => 0,
'status' => 'down',
]);
$ch = curl_init($base . '/app/api/v1/mobile/uptime-checks?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => $email . ':' . $password,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'X-Workspace-Id: ' . $workspaceId,
],
]);
$body = curl_exec($ch);
curl_close($ch);
$json = json_decode((string) $body, true);
foreach ($json['data'] ?? [] as $check) {
echo $check['name'] . ' → ' . ($check['status']['label'] ?? '?') . "\n";
}
const email = '[email protected]';
const password = 'your-password';
const workspaceId = 7;
const base = 'https://geeksuptime.com';
const basic = btoa(`${email}:${password}`);
const url = new URL(`${base}/app/api/v1/mobile/uptime-checks`);
url.searchParams.set('limit', '50');
url.searchParams.set('offset', '0');
url.searchParams.set('status', 'down');
const res = await fetch(url, {
headers: {
Authorization: `Basic ${basic}`,
'X-Workspace-Id': String(workspaceId),
Accept: 'application/json',
},
});
const json = await res.json();
for (const check of json.data ?? []) {
console.log(check.name, check.status?.label);
}
Create an HTTPS check
protocol is http, https, or ping.
check_frequency must be 1, 2, 5, 10, or 15.
trigger_locations must be locations your account can use
(see GET …/uptime-checks/options). Ping checks cannot later become HTTP and vice versa.
curl -sS -u '[email protected]:your-password' \
-H 'X-Workspace-Id: 7' \
-H 'Content-Type: application/json' \
-d '{
"name": "Checkout",
"hostname": "checkout.example.com",
"protocol": "https",
"path": "/health",
"check_frequency": 5,
"request_method": "get",
"response_timeout": 30,
"trigger_locations": ["finland", "iowa"],
"min_failing_locations": 1,
"response_classes": ["2XX"],
"flag_follow_redirect": true,
"notification_group_ids": [12]
}' \
'https://geeksuptime.com/app/api/v1/mobile/uptime-checks'
<?php
$email = '[email protected]';
$password = 'your-password';
$workspaceId = 7;
$base = 'https://geeksuptime.com';
$payload = [
'name' => 'Checkout',
'hostname' => 'checkout.example.com',
'protocol' => 'https',
'path' => '/health',
'check_frequency' => 5,
'request_method' => 'get',
'response_timeout' => 30,
'trigger_locations' => ['finland', 'iowa'],
'min_failing_locations' => 1,
'response_classes' => ['2XX'],
'flag_follow_redirect' => true,
'notification_group_ids' => [12],
];
$ch = curl_init($base . '/app/api/v1/mobile/uptime-checks');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_USERPWD => $email . ':' . $password,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
'X-Workspace-Id: ' . $workspaceId,
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$json = json_decode((string) $body, true);
if ($status !== 201 || empty($json['success'])) {
throw new RuntimeException($json['error']['message'] ?? 'create failed');
}
echo 'Created check #' . $json['data']['id'] . "\n";
const email = '[email protected]';
const password = 'your-password';
const workspaceId = 7;
const base = 'https://geeksuptime.com';
const basic = btoa(`${email}:${password}`);
const res = await fetch(`${base}/app/api/v1/mobile/uptime-checks`, {
method: 'POST',
headers: {
Authorization: `Basic ${basic}`,
'X-Workspace-Id': String(workspaceId),
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
name: 'Checkout',
hostname: 'checkout.example.com',
protocol: 'https',
path: '/health',
check_frequency: 5,
request_method: 'get',
response_timeout: 30,
trigger_locations: ['finland', 'iowa'],
min_failing_locations: 1,
response_classes: ['2XX'],
flag_follow_redirect: true,
notification_group_ids: [12],
}),
});
const json = await res.json();
if (!res.ok || !json.success) {
throw new Error(json.error?.message ?? 'create failed');
}
console.log('Created check', json.data.id);
Resolve an incident
Optional JSON body field resolution_notes.
Acknowledge uses POST …/incidents/{id}/acknowledge with the same auth headers
and no body.
curl -sS -u '[email protected]:your-password' \
-H 'X-Workspace-Id: 7' \
-H 'Content-Type: application/json' \
-d '{"resolution_notes":"Deploy rolled back; latency recovered."}' \
'https://geeksuptime.com/app/api/v1/mobile/incidents/9001/resolve'
<?php
$email = '[email protected]';
$password = 'your-password';
$workspaceId = 7;
$incidentId = 9001;
$base = 'https://geeksuptime.com';
$ch = curl_init($base . '/app/api/v1/mobile/incidents/' . $incidentId . '/resolve');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_USERPWD => $email . ':' . $password,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
'X-Workspace-Id: ' . $workspaceId,
],
CURLOPT_POSTFIELDS => json_encode([
'resolution_notes' => 'Deploy rolled back; latency recovered.',
], JSON_THROW_ON_ERROR),
]);
$body = curl_exec($ch);
curl_close($ch);
$json = json_decode((string) $body, true);
echo ($json['data']['status'] ?? 'unknown') . "\n";
const email = '[email protected]';
const password = 'your-password';
const workspaceId = 7;
const incidentId = 9001;
const base = 'https://geeksuptime.com';
const basic = btoa(`${email}:${password}`);
const res = await fetch(
`${base}/app/api/v1/mobile/incidents/${incidentId}/resolve`,
{
method: 'POST',
headers: {
Authorization: `Basic ${basic}`,
'X-Workspace-Id': String(workspaceId),
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
resolution_notes: 'Deploy rolled back; latency recovered.',
}),
}
);
const json = await res.json();
console.log(json.data?.status);
Endpoint reference
Paths are relative to /app/api/v1.
Basic means HTTP Basic.
WS means X-Workspace-Id is also required.
Mutations on monitoring resources also need an active entitlement unless noted.
Auth & bootstrap
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /mobile/auth/me |
Basic | Profile, workspaces, entitlement |
| POST | /authenticate |
Body credentials | Legacy password check; prefer /mobile/auth/me |
| GET | /mobile/dashboard/summary |
Basic + WS | Counts: checks by state, open incidents, domains |
| GET | /mobile/search |
Basic + WS | Cross-resource search filtered by permissions |
Uptime checks
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /mobile/uptime-checks/options |
Basic + WS | Compatible locations and create options |
| GET | /mobile/uptime-checks |
Basic + WS | Paginated list; filters above |
| POST | /mobile/uptime-checks |
Basic + WS | Create HTTP(S) or ping check |
| GET | /mobile/uptime-checks/{id} |
Basic + WS | Config, groups, latest run |
| POST | /mobile/uptime-checks/{id}/update |
Basic + WS | Replace configuration |
| POST | /mobile/uptime-checks/{id}/delete |
Basic + WS | Delete check |
| POST | /mobile/uptime-checks/{id}/pause |
Basic + WS | Pause monitoring |
| POST | /mobile/uptime-checks/{id}/resume |
Basic + WS | Resume monitoring |
| POST | /mobile/uptime-checks/{id}/favorite |
Basic + WS | Toggle favorite |
| POST | /mobile/uptime-checks/{id}/test-now |
Basic + WS | Run an on-demand probe |
| POST | /mobile/uptime-checks/bulk-pause |
Basic + WS | action pause|resume; optional ids |
| GET | /mobile/uptime-checks/{id}/runs |
Basic + WS | limit, offset, from, to, location, only_failed |
| GET | /mobile/uptime-checks/{id}/latency |
Basic + WS | Latency time series |
| GET | /mobile/uptime-checks/{id}/sla-calendar |
Basic + WS | Availability calendar |
| GET | /mobile/uptime-checks/{id}/export-csv |
Basic + WS | CSV download |
Incidents
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /mobile/incidents |
Basic + WS | status, severity, from, to, pagination |
| GET | /mobile/incidents/{id} |
Basic + WS | Detail, failure locations, notes |
| POST | /mobile/incidents/{id}/acknowledge |
Basic + WS | Idempotent if already acknowledged |
| POST | /mobile/incidents/{id}/resolve |
Basic + WS | Optional resolution_notes |
Domains (SSL)
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /mobile/domains |
Basic + WS | active, expiring_within_days (1–365) |
| POST | /mobile/domains |
Basic + WS | name, optional description, notification_group_ids |
| GET | /mobile/domains/{id} |
Basic + WS | Certificate metadata + groups |
| POST | /mobile/domains/{id}/update |
Basic + WS | Update configuration |
| POST | /mobile/domains/{id}/delete |
Basic + WS | Delete domain |
| POST | /mobile/domains/{id}/toggle |
Basic + WS | Toggle active monitoring |
| POST | /mobile/domains/{id}/check-now |
Basic + WS | Run certificate check now |
| GET | /mobile/domains/{id}/certificate-history |
Basic + WS | Certificate history |
Notification groups
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /mobile/notification-groups |
Basic + WS | List groups in the workspace |
| POST | /mobile/notification-groups |
Basic + WS | Create; at least one channel required |
| GET | /mobile/notification-groups/{id} |
Basic + WS | Channels and expiry-warning schedule |
| POST | /mobile/notification-groups/{id}/update |
Basic + WS |
email_addresses, phone_numbers,
webhook_url, slack_incoming_webhook_url,
push_enabled, trigger_* day flags
|
| POST | /mobile/notification-groups/{id}/delete |
Basic + WS | Delete group |
Maintenance windows
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /mobile/maintenance-windows |
Basic + WS | enabled, state, search, pagination |
| POST | /mobile/maintenance-windows/upsert |
Basic + WS |
Create when id omitted; update when present.
Scope workspace or uptime_check.
|
| POST | /mobile/maintenance-windows/delete |
Basic + WS | JSON body { "id": … } |
Account & devices
| Method | Path | Auth | Notes |
|---|---|---|---|
| POST | /mobile/account/change-password |
Basic | Entitlement-exempt; revokes remember-me tokens |
| POST | /mobile/account/upload-image |
Basic | Multipart profile_image |
| POST | /mobile/push/register-token |
Basic | Register FCM device token |
| POST | /mobile/push/unregister-token |
Basic | Remove device token |
| GET | /mobile/billing/summary |
Basic | Plan, profile, masked card, entitlement snapshot |
Admin-only surfaces also exist for team users, workspaces (including sharing), activity log,
and account update/delete. Those require flag_is_admin and are not covered in depth here.
Stripe Checkout / PaymentSheet endpoints are app-internal; entitlement authority is the billing
lifecycle, not a client “confirm” call.
Outbound events
For push-style automation into your own systems, prefer the
HTTPS webhook on a notification group
(schema_version: 1) instead of polling. Events today:
uptime.check.failed, uptime.check.recovered, and
domain.ssl.expiring_soon.