Go back

How do I update to the latest version of the Oh Dear API

LAST UPDATED on 20th August 2025

IMPORTANT CORRECTION: in some communication we incorrectly said we would launch our new API on Tuesday 23rd of August. That day/date does not exist. The correct date is Tuesday 26th of August

Generally speaking, we don't introduce any breaking changes to our API. On Tuesday 26th of August 2025 however, we will deploy a new version of Oh Dear in which "sites" will be renamed to "monitors" throughout the entire app. In this blog post, you'll learn why we are making this change.

This change also affects our API. In this document, we want to help you understand the changed and give instruction on how to upgrade to the latest version of our API and packages.

We are aware that breaking changes are no fun for you. We will do our utmost best to not introduce any more breaking changes in the foreseeable future.

Which changes will be introduced in our API

In Oh Dear "sites" will be renamed "monitors". This affects our API:

  • The /api/sites/ endpoint will be renamed to /api/monitors
  • Every field / request parameter named site_id will be renamed to monitor_id
  • The /api/performance-records endpoint will be replaced by /api/http-uptime-metrics, /api/ping-uptime-metrics and. /api/tcp-uptime-metrics

We've restructured how we store various parameters for our checks. When you retrieve a monitor from our API, you'll see new fields like uptime_check_settings, broken_link_check_setttings, ... that contains the settings for a check.

When creating or updating a monitor using our API, you can send along these settings fields as well to set or update the properties of a check.

Scheduled tasks monitoring

Our API is often used for syncing scheduled tasks to Oh Dear. That's why we'll keep supporting these existing endpoints:

  • GET /api/sites/<site_id>/cron-checks
  • POST /api/sites/<site_id>/cron-checks
  • POST /api/sites/<site_id>/cron-checks/sync

We will remove support for these endpoints on 1st of August 2026. By then, you should switch to using their /api/monitors/<monitor_id> equivalents.

If you're using v3 of spatie/laravel-schedule-monitor, it will still be able to fully sync your Laravel scheduled tasks to Oh Dear. We do encourage you to upgrade to v4. On 1st of August 2026, syncing your schedule using v3 of the package will not work anymore.

The API towards ping.ohdear.app has not been changed at all, and will continue to work.

Updated packages

On Tuesday 26th of August we'll release a new major version our PHP SDK package and various other packages. On that date, the old versions will not work properly anymore because of the breaking API changes.

You'll find upgrade instructions in the UPGRADE.md that's present in each repository.

Updating your packages before release 26th of August

If you are preparing the upgrade of the packages, you can already install the code as if it was a stable release.

To do this, add these two elements to your composer.json

"minimum-stability": "dev",
"prefer-stable": true

Next, you can install the newest version of any of our new packages.

# only install the packages needed

composer require ohdearapp/ohdear-php-sdk:^4.0
composer require spatie/laravel-schedule-monitor:^4.0
composer require ohdearapp/laravel-ohdear-webhooks:^2.0

These commands will actually pull in the code we have in our development branch.

After we have released our packages, you can simply remove the minimum-stability and prefer-stable keys and run

composer update

This will then pull in the actual released code.

The new monitors endpoint

On 26th of August we'll deploy a new /api/monitors endpoint which replaces the old /api/sites one. It will list all your monitors in your account.

$ OHDEAR_TOKEN="your API token"
$ curl https://ohdear.app/api/monitors \
    -H "Authorization: Bearer $OHDEAR_TOKEN" \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json'

As a result, you get the details for every site you've added.

{
    "data": [
        {
            "id": 1,
            "team_id": 1,
            "type": "http",
            "url": "https://freek.dev",
            "uses_https": true,
            "sort_url": "freek.dev",
            "label": "freek.dev",
            "group_name": "",
            "tags": [],
            "description": null,
            "notes": null,
            "latest_run_date": "2019-09-16 07:29:02",
            "summarized_check_result": "succeeded",
            "checks": [
                {
                    "id": 100,
                    "type": "uptime",
                    "label": "Uptime",
                    "enabled": true,
                    "latest_run_ended_at": "2019-09-16 07:29:02",
                    "latest_run_result": "succeeded",
                    "summary": "Up",
                    "settings": {
                        "uptime_check_location": "paris",
                        "uptime_check_expected_final_redirect_url": null,
                        "uptime_check_failed_notification_threshold": null,
                        "uptime_check_http_verb": null,
                        "uptime_check_timeout": null,
                        "uptime_check_max_redirect_count": null,
                        "uptime_check_payload": null,
                        "uptime_check_valid_status_codes": null,
                        "uptime_check_look_for_string": null,
                        "uptime_check_absent_string": null,
                        "uptime_check_expected_response_headers": null,
                        "http_client_headers": null
                    },
                    "active_snooze": null
                },
                {
                    "id": 101,
                    "type": "broken_links",
                    "label": "Broken links",
                    "enabled": true,
                    "latest_run_ended_at": "2019-09-16 07:29:05",
                    "latest_run_result": "succeeded",
                    "summary": "None",
                    "settings": {
                        "broken_links_check_include_external_links": null,
                        "broken_links_whitelisted_urls": null,
                        "crawler_headers": [],
                        "crawler_speed": "default",
                        "broken_link_types": null,
                        "respect_robots": true
                    },
                    "active_snooze": null
                }
            ],
            "uptime_check_settings": {
                "location": "paris",
                "look_for_string": "",
                "absent_string": null,
                "expected_response_headers": [],
                "failed_notification_threshold": 2,
                "http_verb": "get",
                "payload": [],
                "timeout": 5,
                "valid_status_codes": ["2*"],
                "max_redirect_count": 5,
                "expected_final_redirect_url": null,
                "http_client_headers": []
            },
            "certificate_health_check_settings": {
                "expires_soon_threshold_in_days": null
            },
            "broken_links_check_settings": {
                "whitelisted_urls": [],
                "check_include_external_links": false,
                "types": ["link", "image", "script", "stylesheet", "og:image"],
                "do_not_crawl_urls": [],
                "force_crawl_urls": [],
                "new_links_only": false
            },
            "dns_check_settings": {
                "extra_cnames": [],
                "monitor_main_domain": false,
                "ignored_record_types": ["SOA"],
                "check_nameservers_in_sync": true
            },
            "lighthouse_check_settings": {
                "continent": "europe",
                "cpu_slowdown_modifier": 0,
                "notification_settings": null,
                "preferred_server_name": "lighthouse-checker-frankfurt-1",
                "http_client_headers": []
            },
            "application_health_check_settings": {
                "result_url": null,
                "secret": "your-secret-key",
                "headers": []
            },
            "domain_check_settings": {
                "not_supported_reason": null,
                "expires_soon_threshold_in_days": null
            },
            "performance_check_settings": {
                "threshold_in_ms": 3500,
                "change_percentage": 50
            },
            "sitemap_check_settings": {
                "path": "sitemap.xml",
                "speed": "default"
            },
            "crawler_headers": [],
            "send_report_to_emails": [],
            "include_check_types_in_report": [],
            "badge_id": "badge-123",
            "marked_for_deletion_at": null,
            "created_at": "2019-09-16 07:25:00",
            "updated_at": "2019-09-16 07:25:00"
        },
        {
            "id": 2,
            "team_id": 1,
            "type": "ping",
            "url": "spatie.be",
            "uses_https": false,
            "sort_url": "spatie.be",
            "label": "spatie.be",
            "group_name": "",
            "tags": [],
            "description": null,
            "notes": null,
            "latest_run_date": "2019-09-16 07:30:00",
            "summarized_check_result": "succeeded",
            "checks": [
                {
                    "id": 200,
                    "type": "uptime",
                    "label": "Uptime",
                    "enabled": true,
                    "latest_run_ended_at": "2019-09-16 07:30:00",
                    "latest_run_result": "succeeded",
                    "summary": "Up",
                    "settings": {
                        "uptime_check_location": "paris",
                        "uptime_check_expected_final_redirect_url": null,
                        "uptime_check_failed_notification_threshold": null,
                        "uptime_check_http_verb": null,
                        "uptime_check_timeout": null,
                        "uptime_check_max_redirect_count": null,
                        "uptime_check_payload": null,
                        "uptime_check_valid_status_codes": null,
                        "uptime_check_look_for_string": null,
                        "uptime_check_absent_string": null,
                        "uptime_check_expected_response_headers": null,
                        "http_client_headers": null
                    },
                    "active_snooze": null
                }
            ],
            "uptime_check_settings": {
                "location": "paris",
                "ttl": 64,
                "count": 5,
                "packet_size_in_bytes": 56,
                "acceptable_packet_loss_percentage": 0,
                "acceptable_average_response_time_in_ms": 400,
                "timeout_in_seconds": 1,
                "interval_in_seconds": 1,
                "failed_notification_threshold": 2
            },
            "badge_id": "badge-456",
            "created_at": "2019-09-16 07:26:00",
            "updated_at": "2019-09-16 07:26:00"
        },
        {
            "id": 3,
            "team_id": 1,
            "type": "tcp",
            "url": "smtp.gmail.com:3306",
            "uses_https": false,
            "sort_url": "smtp.gmail.com:3306",
            "label": "smtp.gmail.com:3306",
            "group_name": "",
            "tags": [],
            "description": null,
            "notes": null,
            "latest_run_date": "2019-09-16 07:31:00",
            "summarized_check_result": "succeeded",
            "checks": [
                {
                    "id": 300,
                    "type": "uptime",
                    "label": "Uptime",
                    "enabled": true,
                    "latest_run_ended_at": "2019-09-16 07:31:00",
                    "latest_run_result": "succeeded",
                    "summary": "Up",
                    "settings": {
                        "uptime_check_location": "paris",
                        "uptime_check_expected_final_redirect_url": null,
                        "uptime_check_failed_notification_threshold": null,
                        "uptime_check_http_verb": null,
                        "uptime_check_timeout": null,
                        "uptime_check_max_redirect_count": null,
                        "uptime_check_payload": null,
                        "uptime_check_valid_status_codes": null,
                        "uptime_check_look_for_string": null,
                        "uptime_check_absent_string": null,
                        "uptime_check_expected_response_headers": null,
                        "http_client_headers": null
                    },
                    "active_snooze": null
                }
            ],
            "uptime_check_settings": {
                "location": "paris",
                "tcp_send_string": "",
                "timeout_in_ms": 1000,
                "look_for_string_in_welcome_message": "",
                "look_for_string_in_send_string_response": "",
                "failed_notification_threshold": 2
            },
            "badge_id": "badge-789",
            "created_at": "2019-09-16 07:27:00",
            "updated_at": "2019-09-16 07:27:00"
        }
    ],
    "links": {
        "first": "https://ohdear.app/api/monitors?page%5Bnumber%5D=1",
        "last": "https://ohdear.app/api/monitors?page%5Bnumber%5D=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "https://ohdear.app/api/monitors",
        "per_page": 200,
        "to": 3,
        "total": 3
    }
}

Let's drill this down, because the three monitors shown represent different monitor types:

  1. HTTP Monitor (type: "http"): This is an https:// website monitor that gets comprehensive monitoring including uptime, performance, certificate health, broken links, mixed content, lighthouse, DNS, domain expiration, etc.

  2. Ping Monitor (type: "ping"): This monitors server availability using ICMP ping. It only has uptime checks and uses different settings (TTL, packet size, packet loss percentage, etc.).

  3. TCP Port Monitor (type: "tcp"): This monitors specific TCP port availability (like MySQL, SMTP, etc.). It has uptime checks with TCP-specific settings like connection strings and timeouts.

Each monitor type has different available checks and settings based on what can be monitored. More on each check in our dedicated checks page.

Also notice that the content of the uptime_check_settings depends on the type of monitor.

Get a specific monitor via the API

If you don't want to retrieve all monitors, you can get a specific monitor if you know its ID. The example below will get the details of monitor ID 99.

$ OHDEAR_TOKEN="your API token"
$ curl https://ohdear.app/api/monitors/99 \
    -H "Authorization: Bearer $OHDEAR_TOKEN" \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json'

The resulting response is a single monitor object:

{
  "id": 99,
  "team_id": 1,
  "type": "http",
  "url": "https://example.com",
  "uses_https": true,
  "sort_url": "example.com",
  "label": "example.com",
  "group_name": "",
  "tags": [],
  "description": null,
  "notes": null,
  "latest_run_date": "2019-09-16 07:29:02",
  "summarized_check_result": "succeeded",
  "checks": [
    {
      "id": 100,
      "type": "uptime",
      "label": "Uptime",
      "enabled": true,
      "latest_run_ended_at": "2019-09-16 07:29:02",
      "latest_run_result": "succeeded",
      "summary": "Up",
      "settings": {
        "uptime_check_location": "paris"
      },
      "active_snooze": null
    }
  ],
  "uptime_check_settings": {
    "location": "paris",
    "look_for_string": "",
    "absent_string": null,
    "expected_response_headers": [],
    "failed_notification_threshold": 2,
    "http_verb": "get",
    "payload": [],
    "timeout": 5,
    "valid_status_codes": ["2*"],
    "max_redirect_count": 5,
    "expected_final_redirect_url": null,
    "http_client_headers": []
  },
  "badge_id": "badge-123",
  "marked_for_deletion_at": null,
  "created_at": "2019-09-16 07:25:00",
  "updated_at": "2019-09-16 07:25:00"
}

Notice how this payload does not contain the data wrapper (the API call to retrieve all monitors does).

Monitor Properties

The response gives you comprehensive details for each monitor. Here are the properties:

Core Properties

  • id: Unique internal identifier for the monitor
  • team_id: Every monitor belongs to a Team. This is the team's ID. Since you can belong to multiple teams, the corresponding team ID will be shown for every monitor.
  • type: The monitor type - "http" for websites, "ping" for ICMP ping monitoring, or "tcp" for TCP port monitoring
  • url: The URL/hostname you submitted to Oh Dear (includes protocol for HTTP monitors, hostname for ping, hostname:port for TCP)
  • uses_https: Boolean indicating whether it uses HTTPS (mainly relevant for HTTP monitors)
  • sort_url: The URL without protocol and www. prefix, used for sorting
  • label: Display name for the monitor (defaults to sort_url if no custom name provided)
  • group_name: Name of the group this monitor belongs to (empty string if ungrouped)
  • tags: Array of tag names associated with this monitor
  • description: Optional description for the monitor
  • notes: Custom notes for the monitor
  • latest_run_date: Timestamp of when any check for this monitor last ran
  • summarized_check_result: Overall monitor health - "succeeded", "warning", "failed", or "pending"

Checks Array

  • checks: Array of all checks configured for this monitor. Each check includes:
    • id: Unique identifier for the check
    • type: Check type (uptime, performance, certificate_health, broken_links, mixed_content, lighthouse, cron, application_health, sitemap, dns, domain)
    • label: Human-readable label for the check
    • enabled: Whether this check is currently active
    • latest_run_ended_at: When this specific check last completed
    • latest_run_result: Result of the last run (succeeded, failed, warning, pending, errored-or-timed-out)
    • summary: Human-readable summary of the current status
    • settings: Check-specific configuration (varies by check type)
    • active_snooze: Information about any active notification snoozing

Monitor Type-Specific Settings

Depending on the monitor type, different settings objects are included:

HTTP Monitors (type: "http"):

  • uptime_check_settings: HTTP-specific uptime settings
    • location: Server location for checks (e.g., "paris")
    • look_for_string: Text that must be present in response
    • absent_string: Text that must NOT be present in response
    • expected_response_headers: Headers that must be present
    • failed_notification_threshold: How many failures before alerting
    • http_verb: HTTP method to use ("get", "post", etc.)
    • payload: Request body for POST/PUT requests
    • timeout: Request timeout in seconds
    • valid_status_codes: Array of acceptable HTTP status codes (e.g., ["2*", "3*"])
    • max_redirect_count: Maximum redirects to follow
    • expected_final_redirect_url: Expected final URL after redirects
    • http_client_headers: Custom headers to send with requests

Ping Monitors (type: "ping"):

  • uptime_check_settings: ICMP ping settings
    • location: Server location for checks
    • ttl: Time-to-live for ping packets
    • count: Number of ping packets to send
    • packet_size_in_bytes: Size of each ping packet
    • acceptable_packet_loss_percentage: Maximum acceptable packet loss
    • acceptable_average_response_time_in_ms: Maximum acceptable average response time
    • timeout_in_seconds: Timeout for each ping
    • interval_in_seconds: Interval between pings
    • failed_notification_threshold: How many failures before alerting

TCP Monitors (type: "tcp"):

  • uptime_check_settings: TCP connection settings
    • location: Server location for checks
    • tcp_send_string: String to send after connecting
    • timeout_in_ms: Connection timeout in milliseconds
    • look_for_string_in_welcome_message: Text to look for in initial server response
    • look_for_string_in_send_string_response: Text to look for in response to sent string
    • failed_notification_threshold: How many failures before alerting

Check-Specific Settings Objects

All monitors include these settings objects (even if the checks are disabled):

  • certificate_health_check_settings: SSL certificate monitoring
    • expires_soon_threshold_in_days: Days before expiration to warn
  • broken_links_check_settings: Broken link detection
    • whitelisted_urls: URLs to ignore if broken
    • check_include_external_links: Whether to check external links
    • types: Types of links to check (["link", "image", "script", "stylesheet", "og:image"])
    • do_not_crawl_urls: URLs to exclude from crawling
    • force_crawl_urls: URLs to always crawl
    • new_links_only: Only check newly discovered links
  • dns_check_settings: DNS monitoring configuration
    • extra_cnames: Additional CNAME records to monitor
    • monitor_main_domain: Whether to monitor the main domain
    • ignored_record_types: DNS record types to ignore (["SOA"])
    • check_nameservers_in_sync: Whether to verify nameservers are synchronized
  • lighthouse_check_settings: Performance audit configuration
    • continent: Geographic region for testing ("europe", "america", etc.)
    • cpu_slowdown_modifier: CPU throttling factor
    • notification_settings: Custom notification thresholds
    • preferred_server_name: Specific server to use for testing
    • http_client_headers: Custom headers for the audit
  • application_health_check_settings: Custom application health endpoint
    • result_url: URL of your health check endpoint
    • secret: Secret token for authentication
    • headers: Custom headers to send
  • domain_check_settings: Domain expiration monitoring
    • not_supported_reason: Why domain monitoring isn't available (if applicable)
    • expires_soon_threshold_in_days: Days before expiration to warn
  • performance_check_settings: Response time monitoring
    • threshold_in_ms: Maximum acceptable response time
    • change_percentage: Percentage change threshold for alerts
  • sitemap_check_settings: Sitemap validation
    • path: Path to sitemap file ("sitemap.xml")
    • speed: Crawl speed ("default", "fast", "slow")

Additional Properties

  • crawler_headers: Custom headers sent during crawling operations
  • send_report_to_emails: Email addresses that receive the monthly reports
  • include_check_types_in_report: Which check types are included in monthly reports
  • badge_id: Unique identifier for status badge integration
  • marked_for_deletion_at: Timestamp if monitor is scheduled for deletion
  • created_at: When the monitor was created
  • updated_at: When the monitor was last modified

Want to get started? We offer a no-strings-attached 30 day trial. No credit card required.

Start monitoring

You're all set in
less than a minute!