| Service | Base URL |
|---|---|
| Authentication | https://api.visualping.io |
| Jobs (CRUD) | https://job.api.visualping.io |
| Account/User | https://account.api.visualping.io |
All requests require a Bearer token in the Authorization header. Two auth methods:
Obtained from https://visualping.io/account/developer (up to 5 active keys).
Authorization: Bearer <apiKey>
POST https://api.visualping.io/v2/token
Content-Type: application/json
{
"method": "PASSWORD",
"email": "user@company.com",
"password": "your_password"
}
Response:
{
"id_token": "eyJ...", // valid 24 hours
"refresh_token": "eyJ..." // valid 30 days
}POST https://api.visualping.io/v2/token
Content-Type: application/json
{
"method": "REFRESH_TOKEN",
"refreshToken": "eyJ..."
}
Response:
{
"id_token": "eyJ..."
}GET https://account.api.visualping.io/describe-user
Authorization: Bearer <token>
Returns information about the authenticated user, including their profile and workspaces. Business users also receive an organisation section.
| Field | Type | Description |
|---|---|---|
userId |
integer | Unique user ID |
emailAddress |
string | User's email address |
country |
string | User's country |
locale |
string | Locale code (e.g. en) |
timeZone |
string | User's time zone (e.g. America/Vancouver) |
loginCount |
integer | Total number of logins |
signUpAgeDays |
integer | Days since sign-up |
intentForBusiness |
boolean | Whether the user signed up for business use |
googleChatIntegrated |
boolean | Google Chat integration status |
googleSheetsIntegrated |
boolean | Google Sheets integration status |
slackInstallationStatus |
object | Slack installation details |
refreshToken |
boolean | Whether a refresh token is present |
organisation |
object | Organisation details — business users only (see below) |
workspaces |
array | List of workspaces the user belongs to (see below) |
| Field | Type | Description |
|---|---|---|
id |
integer | Organisation ID |
name |
string | Organisation name |
timeZone |
string | Organisation time zone |
role |
string | User's role in the organisation (e.g. ADMIN) |
plan |
object | Current subscription plan details |
userHasPersonalSubscription |
boolean | Whether the user has a personal subscription |
accountFeatures |
object | Feature flags and limits for the organisation |
balances |
object | Credit balance and renewal info |
counts |
object | Active job and user counts |
trialStartDate |
string (ISO 8601) | Trial start date |
trialEndDate |
string (ISO 8601) | Trial end date |
orgCreatedAt |
string (ISO 8601) | Organisation creation date |
| Field | Type | Description |
|---|---|---|
id |
integer | Workspace ID |
name |
string | Workspace name |
timeZone |
string | Workspace time zone |
role |
string | User's role in this workspace (e.g. ADMIN) |
plan |
object | Workspace subscription plan |
accountFeatures |
object | Feature flags and limits for this workspace |
balances |
object | Credit balance including inOverConsumption flag |
counts |
object | Active job and user counts |
notificationMembers |
array | List of CC email recipients for notifications |
status |
string | Workspace status (e.g. active) |
{
"userId": 123456,
"emailAddress": "user@example.com",
"country": "Canada",
"locale": "en",
"timeZone": "America/Vancouver",
"loginCount": 77,
"slackInstallationStatus": {},
"refreshToken": false,
"organisation": {
"id": 137388,
"name": "Visualping",
"timeZone": "America/Vancouver",
"role": "ADMIN",
"plan": {
"name": "trial_2022.1_active",
"type": "plan",
"subType": "trial_active",
"credits": 500,
"billingPeriod": "monthly",
"label": "Free trial"
},
"userHasPersonalSubscription": false,
"accountFeatures": {
"reports": { "enabled": true },
"exports": { "enabled": true },
"bulkImport": { "enabled": true },
"ccEmails": { "enabled": true, "maxAddressCount": 5 },
"sms": { "enabled": true },
"advancedNotifications": { "enabled": true },
"maxActiveJobsPerWorkspace": { "value": 25 },
"maxJobFrequency": { "value": 1 },
"emailSupport": { "enabled": true },
"dedicatedSupport": { "enabled": true }
},
"balances": {
"nextCreditRenewalAt": "2026-06-11T19:19:59.170Z",
"estimatedMonthlyConsumption": 774
},
"counts": {
"activeJobCount": 2,
"activeJobFreeCount": 23,
"activeJobOverflow": false,
"activeUserCount": 4,
"activeUserFreeCount": 6,
"activeUserOverflow": false
},
"trialStartDate": "2026-05-07T19:19:59.170Z",
"trialEndDate": "2026-05-21T19:19:59.170Z",
"orgCreatedAt": "2026-05-07T19:19:59.000Z"
},
"workspaces": [
{
"id": 137389,
"name": "Workspace #1",
"timeZone": "America/Vancouver",
"role": "ADMIN",
"plan": { "name": "trial_2022.1_active", "label": "Free trial" },
"balances": {
"credits": 146,
"nextCreditRenewalAt": "2055-11-21T19:19:59.170Z",
"estimatedMonthlyConsumption": 732,
"inOverConsumption": true
},
"counts": {
"activeJobCount": 1,
"activeJobFreeCount": 499999,
"activeJobOverflow": false
},
"notificationMembers": [{ "type": "ccEmail", "value": "user@example.com", "confirmed": true }],
"status": "active"
}
]
}GET https://job.api.visualping.io/v2/jobs
Authorization: Bearer <token>
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| workspaceId | integer | Yes (business users) | — | Workspace ID |
| mode | string | No | normal |
Output mode: counts_only, ids_and_wsIds, ids_only, normal |
| pageIndex | integer | No | 0 | Page number (0-based) |
| pageSize | integer | No | 100 | Jobs per page (min 1) |
| activeFilter | array[int] | No | — | Filter: 0 (paused), 1 (active) |
| modeFilter | array[string] | No | — | Filter by mode: VISUAL, WEB, TEXT |
| frequencyFilter | array[string] | No | — | Filter by frequency bucket |
| hasAdvancedScheduleFilter | int (0/1) | No | — | Filter by advanced schedule presence |
| eventFilter | string | No | — | Filter by event: changed, changedImportant, errored, checked |
| dateFilter | string | No | — | Time interval for eventFilter |
| dateFilterStart | string | No | — | ISO date, required if dateFilter is since_custom_date |
| fullTextSearchFilter | string | No | — | Search in URLs/descriptions |
| labelsFilter | array[int] | No | — | Filter by label IDs |
| sortBy | array[string] | No | active_first,lastrun_desc |
Sort order |
sortBy options: id_asc, id_desc, created_asc, created_desc, lastrun_asc, lastrun_desc, active_first, inactive_first, frequency_asc, frequency_desc, alphabetical_asc, alphabetical_desc, last_diff_detected_asc, last_diff_detected_desc
POST https://job.api.visualping.io/v2/jobs
Authorization: Bearer <token>
Content-Type: application/json
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| workspaceId | integer | Yes (business) | — | Workspace ID |
| url | string | Yes | — | URL to monitor |
| description | string | No | — | Human-readable label for the job |
| mode | string | No | ALL |
Monitor mode. Options: VISUAL, WEB, TEXT, ALL. Default ALL — most users should not change this. |
| active | boolean | No | true | Whether the job starts active |
| interval | string | No | "1440" |
Check frequency in minutes (as a string). Default "1440" (once per day). Common values: "5", "15", "30", "60", "360", "720", "1440". |
| trigger | string | No | "1" |
Sensitivity threshold. Default "1". Most users should not change this. |
| crop | object | No | — | Screen region to monitor: { x, y, width, height } |
| proxy_id | integer | No | — | Proxy to use |
| xpath | string | No | — | XPath or CSS selector to target a specific element |
| keyword_action | string | No | ALL |
Keyword filter mode |
| keywords | string | No | — | Keywords to filter changes |
| disable_js | boolean | No | false | Disable JavaScript rendering |
| enable_cookies_and_ad_blocker | boolean | No | false | Enable cookies and ad blocking |
| preactions | object | No | — | Actions to perform before checking (click, type, etc.) |
| advanced_schedule | object | No | — | Restrict checks to specific times/days |
| notification | object | No | — | Notification configuration (see below) |
| retention_policy | string | No | "3" |
History retention policy |
| alert_error | boolean | No | true | Alert on errors |
| summalyzer | object | No | — | AI summary configuration (see below) |
| labelIds | array[int] | No | — | Labels to attach. See §11–15 for managing labels and bulk job↔label assignment. |
{
"enableSmsAlert": true,
"enableEmailAlert": true,
"onlyImportantAlerts": true,
"config": {
"slack": { "url": "webhook_url", "active": true, "notificationType": "slack", "channels": ["#channel"] },
"teams": { "url": "webhook_url", "active": true, "notificationType": "slack", "channels": ["#channel"] },
"webhook": { "url": "https://your-endpoint.com", "active": true, "notificationType": "slack", "channels": [] },
"discord": { "url": "webhook_url", "active": true, "notificationType": "slack", "channels": ["#channel"] },
"slack_app": { "url": "...", "active": true, "notificationType": "slack", "channels": ["#channel"] },
"google_sheets": { "url": "...", "active": true, "notificationType": "slack", "channels": [] },
"google_chat": { "url": "...", "active": true, "notificationType": "slack", "channels": [] }
}
}| Field | Type | Values | Description |
|---|---|---|---|
importantDefinitionType |
string | "default", "custom", "none" |
Set to "custom" when user provides an importance definition. Otherwise "default". |
importantDefinition |
string | — | User's description of what changes matter. Only include when importantDefinitionType is "custom". |
With user-defined importance (recommended — encourage users to provide this):
{
"importantDefinition": "Price drops below $50 or item goes out of stock",
"importantDefinitionType": "custom"
}Without (fallback):
{
"importantDefinitionType": "default"
}{
"stop_time": 18,
"start_time": 9,
"active_days": [1, 2, 3, 4, 5]
}Days: 1=Monday through 7=Sunday. Times are 0-24 (hours).
{
"active": true,
"actions": [
{ "action": "click", "selector": "#button-id" },
{ "action": "type", "selector": "#input-id", "value": "text to type" }
]
}POST https://job.api.visualping.io/v2/jobs/from-saved-settings
Authorization: Bearer <token>
Content-Type: application/json
Creates a job by reusing saved job settings (preset/default preset).
- Business users only.
- Requires saved settings to exist for the organization that the workspace belongs to.
- If
savedJobSettingsIdis omitted, the workspace default preset is used.
| Field | Type | Required | Description |
|---|---|---|---|
| workspaceId | integer | Yes (business) | ID of the workspace where the job will be added |
| url | string | Yes | URL to monitor |
| savedJobSettingsId | integer | No | Saved settings ID to apply; if omitted, uses workspace default preset |
| description | string | No | Human-readable label for the job |
| interval | string | No | Optional override (minutes as string). Only include when explicitly overriding saved settings. |
{
"workspaceId": 137389,
"url": "https://example.com",
"savedJobSettingsId": 12345,
"description": "Weekly check from preset"
}PUT https://job.api.visualping.io/v2/jobs/bulk
Authorization: Bearer <token>
Content-Type: application/json
Creates many jobs in a single request, applying a shared settings block to every URL in the jobs array. Use this for importing lists of URLs (e.g. CSV upload, onboarding) where every job should share the same monitoring configuration.
Despite using PUT, this endpoint creates new jobs — it does not update existing ones.
| Field | Type | Required | Description |
|---|---|---|---|
| settings | object | Yes | Shared configuration applied to every job. Same shape as Create Job body (without url). |
| jobs | array[object] | Yes | One entry per job to create. Each entry must include url; per-job overrides are also supported. |
| workspaceId | integer | Yes (business) | Workspace where the jobs will be created |
| initToBlank | boolean | No | If true, jobs start with a blank baseline (no initial screenshot used as reference) |
The settings object accepts every field documented under §3 Create Job (e.g. mode, interval, trigger, notification, preactions, labelIds, enable_cookies_and_ad_blocker, target_device, wait_time, etc.).
Each entry in jobs must contain at least url. Any field accepted by Create Job may be included on a per-job basis to override the shared settings for that one URL (e.g. a custom description or xpath).
{
"workspaceId": 4139,
"initToBlank": false,
"settings": {
"active": true,
"mode": "ALL",
"interval": "1440",
"trigger": "0.01",
"notification_threshold": 0.01,
"target_device": "4",
"wait_time": 0,
"enable_cookies_and_ad_blocker": true,
"alert_error": false,
"labelIds": [142819],
"preactions": {
"active": true,
"actions": [{ "click": "home" }]
},
"notification": {
"enableSmsAlert": false,
"enableEmailAlert": true,
"onlyImportantAlerts": true,
"config": {
"webhook": { "url": "", "active": false, "notificationType": "webhook" }
}
},
"summalyzer": { "importantDefinitionType": "none" }
},
"jobs": [
{ "url": "https://example.com/page-1" },
{ "url": "https://example.com/page-2", "description": "Pricing page" }
]
}GET https://job.api.visualping.io/v2/jobs/{jobId}
Authorization: Bearer <token>
| Parameter | Type | Required | Description |
|---|---|---|---|
| jobId | integer | Yes | Job ID |
| Parameter | Type | Required | Description |
|---|---|---|---|
| workspaceId | integer | Business users | Workspace ID |
{
"id": "string",
"url": "string",
"description": "string",
"mode": "VISUAL",
"active": true,
"interval": 1440,
"runs": 0,
"error_count": 0,
"in_progress": true,
"scheduled_at": "ISO date",
"last_run": "ISO date",
"next_run": "ISO date",
"crop": { "x": 0, "y": 0, "width": 0, "height": 0 },
"xpath": "string",
"notification": { "..." },
"advanced_schedule": { "..." },
"thumb_full": "screenshot URL",
"thumb_150": "thumbnail URL",
"favicon": "favicon URL",
"history": [
{
"created": "ISO date",
"mode": "VISUAL",
"PercentDifference": 0,
"diff": {
"nodePercentDiff": 0,
"areaPercentDiff": 0,
"wordPercentDiff": 0,
"pixelPercentDiff": 0,
"VISUAL": 0,
"TEXT": 0
},
"image": "screenshot URL",
"error_message": "string or null",
"notification_send": true,
"initial": false
}
],
"changes": [
{
"created": "ISO date",
"mode": "VISUAL",
"PercentDifference": 0,
"diff": { "..." },
"thumb_diff_full": "diff image URL",
"htmlDiffUrl": "HTML diff URL",
"englishSummary": "AI-generated summary of the change",
"analyzerAlertTriggered": true,
"feedback": { "DIFF": "GOOD", "SUMMARY": "GOOD" }
}
],
"summalyzer": { "..." },
"labelIds": [0],
"retention_policy": "3"
}PUT https://job.api.visualping.io/v2/jobs/{jobId}
Authorization: Bearer <token>
Content-Type: application/json
Request body is the same shape as Create Job. Only include fields you want to change.
DELETE https://job.api.visualping.io/v2/jobs/{jobId}
Authorization: Bearer <token>
| Parameter | Type | Required | Description |
|---|---|---|---|
| workspaceId | integer | Business users | Workspace ID |
POST https://job.api.visualping.io/v2/jobs/report-page
Authorization: Bearer <token>
Content-Type: application/json
Returns a reverse-chronological flat list of check history items across all jobs in a workspace. Use this for activity feeds, dashboards, digests, and audit views.
| Field | Type | Required | Description |
|---|---|---|---|
| workspaceId | integer | Yes | Workspace ID |
| scope.comboId | integer | Yes | Negative of workspaceId (e.g. workspace 4348 → -4348) |
| includeErrors | boolean | No | Include failed checks in the feed (default: false) |
| level | string | No | "allChecks" to get everything; other values may filter by change level |
{
"workspaceId": 4348,
"scope": { "comboId": -4348 },
"includeErrors": true,
"level": "allChecks"
}{
"count": 100,
"items": [...]
}Each item in items represents a single check run for a job:
| Field | Description |
|---|---|
jobId |
Numeric job ID |
description |
Job name/label |
url |
Monitored URL |
screenshotLogId |
Unique ID for this check run |
screenshotLogCreated |
ISO timestamp of the check |
processId |
Internal processing ID |
changeDetectionLevel |
"important", "regular", "minor-threshold", "minor-importance", "none", or absent (initial check) |
notificationSent |
Whether an alert was triggered |
aiOutput.changeSummary |
AI-generated description of what changed |
aiOutput.changeIsImportant |
Boolean: whether the AI judged the change as important |
aiOutput.changeIsImportantReason |
Explanation of why the change was or wasn't flagged as important |
matchedKeywords |
Array of any keywords that matched |
currentScreenshotKey |
S3-style key for the current screenshot |
previousScreenshotKey |
S3-style key for the previous screenshot |
currentUncroppedScreenshotKey |
S3-style key for the full-page current screenshot |
previousUncroppedScreenshotKey |
S3-style key for the full-page previous screenshot |
diffImageKey |
Key for the visual diff image |
insertedImageKey |
Key for inserted content image |
deletedImageKey |
Key for deleted content image |
faviconKey |
Key for the site favicon |
disableId |
Token used to unsubscribe from alerts |
errorLogId |
Present on failed checks |
errorMessage |
Error description (if errored) |
errorLabel |
Short error label (if errored) |
comments |
Array of user comments: { authorName, text, created } |
Notes:
- Items with no
changeDetectionLeveland noerrorLogIdare initial baseline snapshots. - Results are sorted newest-first and are interleaved across jobs (not grouped by job).
- The response is paginated at 100 items — additional pagination parameters may apply.
POST https://job.api.visualping.io/v2/jobs/launch
Authorization: Bearer <token>
Content-Type: application/json
Manually triggers an immediate check for one or more jobs.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| jobIds | array[int] | Yes | — | Job IDs to run now |
| workspaceId | integer | Business | — | Workspace ID |
| restartSchedule | boolean | No | false | If true, the job's recurring schedule is reset to start from now |
{ "jobIds": [6024347], "restartSchedule": false, "workspaceId": 2456 }GET https://job.api.visualping.io/v2/jobs/labels
Authorization: Bearer <token>
Labels are scoped to the organisation, not the workspace.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| organisationId | integer | Yes | — | Organisation ID (note British spelling) |
| sortBy | string | No | — | e.g. alphabetical_asc, alphabetical_desc |
| computeUsage | int (0/1) | No | 0 | If 1, each label includes numOfJobsLabeled |
POST https://job.api.visualping.io/v2/jobs/labels
Authorization: Bearer <token>
Content-Type: application/json
Creates one or more labels in a single request.
| Field | Type | Required | Description |
|---|---|---|---|
| organisationId | integer | Yes | Organisation ID |
| labels | array[object] | Yes | Labels to create |
Label object (for creation):
| Field | Type | Required | Description |
|---|---|---|---|
| id | integer | Yes | Use a negative sentinel (-1, -2, …) to indicate a new label; the server assigns the real ID |
| name | string | Yes | Label name |
| color | string | Yes | Hex color, e.g. "#FFFAEB" |
| emoji | string | No | Emoji shortcode, e.g. ":new:" |
{
"organisationId": 2455,
"labels": [
{ "id": -1, "name": "tmp", "color": "#FFFAEB", "emoji": ":new:" },
{ "id": -2, "name": "tmp2", "color": "#FDF2FA", "emoji": ":new:" }
]
}PUT https://job.api.visualping.io/v2/jobs/labels
Authorization: Bearer <token>
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
| organisationId | integer | Yes | Organisation ID |
| labels | array[object] | Yes | Labels to update; each must use the real (positive) id |
numOfJobsLabeled is accepted in the payload but is effectively read-only.
{
"organisationId": 2455,
"labels": [
{ "id": 9, "name": "tmp3", "emoji": ":new:", "color": "#FFFAEB", "numOfJobsLabeled": 0 }
]
}DELETE https://job.api.visualping.io/v2/jobs/labels
Authorization: Bearer <token>
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
| id | integer | Yes | Label ID to delete (single, not an array) |
| organisationId | integer | Yes | Organisation ID |
{ "id": 10, "organisationId": 2455 }PUT https://job.api.visualping.io/v2/jobs/joblabels
Authorization: Bearer <token>
Content-Type: application/json
Bulk add or remove labels across one or more jobs in a single call.
| Field | Type | Required | Description |
|---|---|---|---|
| organisationId | integer | Yes | Organisation ID |
| jobIds | array[int] | Yes | Jobs to update |
| addLabelIds | array[int] | No | Label IDs to add |
| removeLabelIds | array[int] | No | Label IDs to remove |
{
"organisationId": 2455,
"jobIds": [6024347],
"addLabelIds": [9, 10],
"removeLabelIds": [12]
}| Interval (string) | Human-readable |
|---|---|
"5" |
Every 5 minutes |
"15" |
Every 15 minutes |
"30" |
Every 30 minutes |
"60" |
Every hour |
"360" |
Every 6 hours |
"720" |
Every 12 hours |
"1440" |
Once a day (default) |
"10080" |
Once a week |
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request / invalid parameters |
| 403 | Forbidden / auth failure |
| 500 | Server error |