Different payloads for our Webhook events

Oh Dear will notify you of each event if you've enabled webhooks. Here, we'll list all events we can fire.

For easy debugging, we recommend using a service like webhook.site, which can show you the payload of the webhook data in real-time.

Table of content #

There's a lot of data on this page, you can jump directly to your desired payload with the table of contents shown below.

Generic payloads #

All webhook data will contain a set of recurring data points.

First, there's confirmation about which event you're receiving and which date this was generated.

{
    "type":"uptimeCheckFailed",
    "date_time":"20180312092737",
    ...
}

Next, there are details on the site that this event took place on. This will look like this:

{
    ...
    "site":{
        "id":1,
        "url":"https:\/\/yoursite.tld",
        "uses_https":true,
        "sort_url":"yoursite.tld",
        "label": "my-site",
        "team_id":1,
        "latest_run_date":"2018-03-12 20:27:34",
        "summarized_check_result":"failed",
        "created_at":"2018-03-12 20:24:54",
        "updated_at":"2018-03-12 20:24:54",
        "checks":[
            {
                "id":1,
                "type":"uptime",
                "enabled":true,
                "human_readable_check_type":"Uptime",
                "site_id":1,
                "latest_run_result":"failed",
                "latest_run_ended_at":"2018-03-12 20:27:34",
                "latest_run_id":2,
                "latest_run_report_url":"https:\/\/ohdear.app\/sites\/1\/history\/runs\/1",
                "always_running":false
            },
            ...
        ]
    },
}

Additionally, there is meta-data present about the time the event took place.

"run":{
    ...
    "started_at":"2018-03-12 20:27:33",
    "ended_at":"2018-03-12 20:27:34",
    "created_at":"2018-03-12 20:27:31",
    "updated_at":"2018-03-12 20:27:34",
}

The actual payload of each individual event can be found in the runs block, which contains all relevant data pertaining to the event that just happened. Each of those blocks will be updated in more detail below.

Site added #

Whenever you add a site to your Oh Dear! account, we'll send a webhook for the siteAddedNotification type with this data.

Included in the payload are details like the site ID and the checks that were included and their IDs. The checks will still be pending, but you can use the the check IDs to retrieve their latest details using our API.

{
   "type":"siteAddedNotification",
   "date_time":"20191001113659",
   "site":{
      "id":1,
      "url":"https:\/\/yoursite.tld",
      "uses_https":true,
      "sort_url":"yoursite.tld",
      "label":"yoursite.tld",
      "team_id":1,
      "latest_run_date":null,
      "summarized_check_result":"pending",
      "created_at":"2019-10-01 09:36:59",
      "updated_at":"2019-10-01 09:36:59",
      "checks":[
         {
            "id":39675,
            "type":"uptime",
            "enabled":true,
            "human_readable_check_type":"Uptime",
            "site_id":1,
            "latest_run_result":"pending",
            "latest_run_ended_at":null,
            "latest_run_id":null,
            "latest_run_report_url":"https:\/\/ohdear.app\/sites\/1\/history\/runs",
            "always_running":false
         },
         {
            "id":39676,
            "type":"broken_links",
            "enabled":true,
            "human_readable_check_type":"Broken links",
            "site_id":1,
            "latest_run_result":"pending",
            "latest_run_ended_at":null,
            "latest_run_id":null,
            "latest_run_report_url":"https:\/\/ohdear.app\/sites\/1\/history\/runs",
            "always_running":false
         },
         {
            "id":39677,
            "type":"mixed_content",
            "enabled":true,
            "human_readable_check_type":"Mixed content",
            "site_id":1,
            "latest_run_result":"pending",
            "latest_run_ended_at":null,
            "latest_run_id":null,
            "latest_run_report_url":"https:\/\/ohdear.app\/sites\/1\/history\/runs",
            "always_running":false
         },
         {
            "id":39678,
            "type":"certificate_health",
            "enabled":true,
            "human_readable_check_type":"Certificate health",
            "site_id":1,
            "latest_run_result":"pending",
            "latest_run_ended_at":null,
            "latest_run_id":null,
            "latest_run_report_url":"https:\/\/ohdear.app\/sites\/1\/history\/runs",
            "always_running":false
         },
         {
            "id":39679,
            "type":"certificate_transparency",
            "enabled":true,
            "human_readable_check_type":"Certificate transparency",
            "site_id":1,
            "latest_run_result":null,
            "latest_run_ended_at":null,
            "latest_run_id":null,
            "latest_run_report_url":"https:\/\/ohdear.app\/sites\/1\/history\/runs",
            "always_running":true
         }
      ]
   }
}

Uptime monitor: downtime detected #

When we detect your website is down, we'll send a webhook for the uptimeCheckFailed type with this data.

{
   "type":"uptimeCheckFailed",
   "date_time":"20180312092737",
   "site":{
      "id":1,
      ... /* See above */
   },
   "run":{
      "id":19830466,
      "check_id":10988,
      "parameters":null,
      "result":"failed",
      "result_payload":{
         "checkerResult":{
            "checkerServer":{
               "name":"uptime-checker-paris",
               "city":"Paris",
               "country":"France",
               "ip":"45.32.146.84"
            },
            "response":[

            ],
            "lookForString":"",
            "lookForStringFound":true,
            "error":{
               "type":"connectionError",
               "errorNumber":6,
               "description":"Could not resolve host: yoursite.tld"
            },
            "statistics":{
               "url":"https:\/\/yoursite.tld\/",
               "content_type":null,
               "http_code":0,
               "header_size":0,
               "request_size":0,
               "filetime":-1,
               "ssl_verify_result":0,
               "redirect_count":0,
               "total_time":7.6000000000000004184153024056058711721561849117279052734375e-5,
               "namelookup_time":0,
               "connect_time":0,
               "pretransfer_time":0,
               "size_upload":0,
               "size_download":0,
               "speed_download":0,
               "speed_upload":0,
               "download_content_length":-1,
               "upload_content_length":-1,
               "starttransfer_time":0,
               "redirect_time":0,
               "redirect_url":"",
               "primary_ip":"",
               "certinfo":[

               ],
               "primary_port":0,
               "local_ip":"",
               "local_port":0
            }
         },
         "alternativeLocationCheckerResult":{
            "checkerServer":{
               "name":"uptime-checker-bangalore",
               "city":"Bangalore",
               "country":"India",
               "ip":"139.59.75.39"
            },
            "response":[

            ],
            "lookForString":"",
            "lookForStringFound":true,
            "error":{
               "type":"connectionError",
               "errorNumber":6,
               "description":"Could not resolve host: yoursite.tld"
            },
            "statistics":{
               "url":"https:\/\/yoursite.tld\/",
               "content_type":null,
               "http_code":0,
               "header_size":0,
               "request_size":0,
               "filetime":-1,
               "ssl_verify_result":0,
               "redirect_count":0,
               "total_time":6.600000000000000506018837942434629439958371222019195556640625e-5,
               "namelookup_time":0,
               "connect_time":0,
               "pretransfer_time":0,
               "size_upload":0,
               "size_download":0,
               "speed_download":0,
               "speed_upload":0,
               "download_content_length":-1,
               "upload_content_length":-1,
               "starttransfer_time":0,
               "redirect_time":0,
               "redirect_url":"",
               "primary_ip":"",
               "certinfo":[

               ],
               "primary_port":0,
               "local_ip":"",
               "local_port":0
            }
         }
      },
   }
}

Uptime monitor: recovery detected #

When site comes back up, we'll send a webhook for the uptimeCheckRecovered type with this data.

{
   "type":"uptimeCheckRecovered",
   "date_time":"20191001112131",
   "run":{
      "id":423131444,
      "check_id":33859,
      "parameters":[

      ],
      "result":"succeeded",
      "result_payload":{
         "checkerResult1":{
            "checkerServer":{
               "name":"uptime-checker-paris",
               "city":"Paris",
               "country":"France",
               "ip":"45.32.146.84"
            },
            "response":{
               "code":200,
               "code_phrase":"OK",
               "protocol":"1.1",
               "headers":{
                  "Server":[
                     "nginx"
                  ],
                  "Date":[
                     "Tue, 01 Oct 2019 09:21:30 GMT"
                  ],
                  "Content-Type":[
                     "text\/html; charset=UTF-8"
                  ],
                  "Transfer-Encoding":[
                     "chunked"
                  ],
                  "Connection":[
                     "keep-alive"
                  ],
                  "Vary":[
                     "Accept-Encoding",
                     "Accept-Encoding"
                  ],
                  "Cache-Control":[
                     "private, must-revalidate"
                  ],
                  "pragma":[
                     "no-cache"
                  ],
                  "expires":[
                     "-1"
                  ],
                  "Set-Cookie":[
                     "XSRF-TOKEN=eyJpdiI6InlNSkJOQVpwb2sra0c2Y0tsRkp5TEE9PSIsInZhbHVlIjoiUXVweXRIWXlxT1Q0U0hrUmUyTTh2K3lXd1EyM1VkcGwzUG1RN2g4a2tVcXpITU5ZVitGU05QRTlhWFFvTTQzdWpmZlFSbk9kYWZoR2V5ZTc1dVR0QlE9PSIsIm1hYyI6IjNkZDIyMGU2ZDMzOGJkMmYzMGU1N2QwNmNiOWE0MmJmODc3YWRjZGQ4NWEwY2IyYjE0ZGQ1ZTA1YjI2NWQwYzgifQ%3D%3D; expires=Tue, 01-Oct-2019 11:21:30 GMT; Max-Age=7200; path=\/",
                     "laravel_session=eyJpdiI6IkxLVUFIY1BWMHE2bGNuTTFGYkp1SkE9PSIsInZhbHVlIjoiZGhHZFlIOHBpbTFSWGM4RFgwcFlwUlwvMThlUkFKYUdqU0tGRVVldGNDY3ZwRXc5dEh4K1wvWVY1MFk0R2UxZU5kVk9CMFppYkpBdStUVEFKb1FCR3RRZz09IiwibWFjIjoiZGI2ZjdjYjgxY2ZiZTQ1MGNiYzAzMzE1ZWNlNjdlMjExNWE3MjFhZTRiMWZhYTcwYjExMDVjMTNkYzRkZjFlYiJ9; expires=Tue, 01-Oct-2019 11:21:30 GMT; Max-Age=7200; path=\/; httponly"
                  ]
               }
            },
            "lookForString":"",
            "lookForStringFound":true,
            "error":[

            ],
            "statistics":{
               "url":"https:\/\/immutable.be\/",
               "content_type":"text\/html; charset=UTF-8",
               "http_code":200,
               "header_size":1024,
               "request_size":152,
               "filetime":-1,
               "ssl_verify_result":0,
               "redirect_count":0,
               "total_time":0.110265000000000001900701818158267997205257415771484375,
               "namelookup_time":0.0042430000000000002435829316027593449689447879791259765625,
               "connect_time":0.01140900000000000073796524446834155241958796977996826171875,
               "pretransfer_time":0.058913000000000000089261931179862585850059986114501953125,
               "size_upload":0,
               "size_download":3227,
               "speed_download":29265,
               "speed_upload":0,
               "download_content_length":-1,
               "upload_content_length":-1,
               "starttransfer_time":0.10999699999999999755484481056555523537099361419677734375,
               "redirect_time":0,
               "redirect_url":"",
               "primary_ip":"31.193.180.217",
               "certinfo":[

               ],
               "primary_port":443,
               "local_ip":"45.32.146.84",
               "local_port":36260
            }
         }
      },
      ...
   },
   "site":{
      "id":1,
      ... /* See above */
   }
}

Whenever a crawl of your site is finished, and broken links were found, we'll send a webhook for the brokenLinksFound type with this data.

{
   "type":"brokenLinksFound",
   "date_time":"20191001114254",
   "run":{
      "id":423155781,
      "check_id":39681,
      "parameters":[

      ],
      "result":"failed",
      "result_payload":{
         "broken_links":[
            {
               "crawled_url":"https:\/\/immutable.be\/broken-links-test-page\/0\/404",
               "status_code":404,
               "found_on_url":"https:\/\/immutable.be\/broken-links-test-page\/"
            },
            {
               "crawled_url":"https:\/\/immutable.be\/broken-links-test-page\/1\/404",
               "status_code":404,
               "found_on_url":"https:\/\/immutable.be\/broken-links-test-page\/"
            },
            ...
         ],
         "crawled_urls":[
            {
               "crawled_url":"https:\/\/immutable.be\/broken-links-test-page\/",
               "status_code":200,
               "found_on_url":""
            },
            {
               "crawled_url":"https:\/\/immutable.be\/broken-links-test-page\/0\/404",
               "status_code":404,
               "found_on_url":"https:\/\/immutable.be\/broken-links-test-page\/"
            },
            ...
         ],
         "whitelist":null
      },
      ...
   },
   "site":{
      "id":1,
      ... /* see above */
   }
}

When we detect that all broken links have been fixed, we'll send a webhook for the brokenLinksFixed type with this data.

{
   "type":"brokenLinksFixed",
   "date_time":"20191001114436",
   "run":{
      "id":423159529,
      "check_id":39681,
      "parameters":[

      ],
      "result":"succeeded",
      "result_payload":{
         "broken_links":[

         ],
         "crawled_urls":[
            {
               "crawled_url":"https:\/\/immutable.be\/broken-links-test-page\/",
               "status_code":200,
               "found_on_url":""
            },
            {
               "crawled_url":"https:\/\/immutable.be\/broken-links-test-page\/?0-404",
               "status_code":200,
               "found_on_url":"https:\/\/immutable.be\/broken-links-test-page\/"
            },
            ...
         ],
         "whitelist":null
      },
      ...
   },
   "site":{
      "id":1,
      ... /* see above */
   }
}

Mixed content found #

When we detected mixed content, we'll send a webhook for the mixedContentFound type with this data.

There's a special note here: the result_payload contains a serialized array with instances of the Spatie\MixedContentScanner\MixedContent model.

To use, first unserialize() the data and treat each element in the resulting array as a model of MixedContent.

{
   "type":"mixedContentFound",
   "date_time":"20191001114652",
   "run":{
      "id":423161645,
      "check_id":39687,
      "parameters":[

      ],
      "result":"failed",
      "result_payload":{
         "foundMixedContent":"a:9:{i:0;O:39:\"Spatie\\MixedContentScanner\\MixedContent\":3:{s:11:\"elementName\";s:3:\"img\";s:15:\"mixedContentUrl\";O:19:\"GuzzleHttp\\Psr7\\Uri\":7:{s:27:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000scheme\";s:4:\"http\";s:29:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000userInfo\";s:0:\"\";s:25:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000host\";s:16:\"doesnotexist.tld\";s:25:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000port\";N;s:25:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000path\";s:11:\"\/image0.png\";s:26:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000query\";s:0:\"\";s:29:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000fragment\";s:0:\"\";}s:10:\"foundOnUrl\";O:19:\"GuzzleHttp\\Psr7\\Uri\":7:{s:27:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000scheme\";s:5:\"https\";s:29:\"\u0000GuzzleHttp\\Psr7\\Uri\u0000userInfo\";s:0:\"\";...",
         "pagesWithoutMixedContent":0,
         "crawledPages":"a:1:{i:0;s:45:\"https:\/\/site.tld\/\";}"
      },
      ...
   },
   "site":{
      "id":1,
      ... /* see above */
   }
}

Mixed content fixed #

When the mixed content was found to be fixed, we'll send a webhook for the mixedContentFixed type with this data.

{
   "type":"mixedContentFixed",
   "date_time":"20191001115320",
   "run":{
      "id":423169009,
      "check_id":39687,
      "parameters":[

      ],
      "result":"succeeded",
      "result_payload":{
         "foundMixedContent":"a:0:{}",
         "pagesWithoutMixedContent":1,
         "crawledPages":"a:1:{i:0;s:45:\"https:\/\/site.tld\/\";}"
      },
      ...
   },
   "site":{
      "id":1,
      ... /* see above */
   }
}

Certificate found to be unhealthy #

When we detect issues with your certificate, we'll send a webhook for the certificateUnhealthy type with this data.

There's a special note here: the result_payload contains a serialized array with instances of the certificateChain model.

To use, first unserialize() the data and treat each element in the resulting array as a model of SslCertificate.

You'll find most things you need in the issues[] array, which contains an array of strings with human-readable notices about the problems we detected.

{
   "type":"certificateUnhealthy",
   "date_time":"20191001115620",
   "run":{
      "id":423172975,
      "check_id":39698,
      "parameters":[

      ],
      "result":"failed",
      "result_payload":{
         "issues":{
            "coversWrongDomain":"Certificate does not cover `https:\/\/neverssl.com\/` but `*.cloudfront.net`."
         },
         "certificateChain":"O:68:\"App\\Domain\\Check\\Support\\Checkers\\CertificateHealth\\CertificateChain\":4:{s:7:\"\u0000*\u0000site\";s:21:\"https:\/\/neverssl.com\/\";s:11:\"\u0000*\u0000hostName\";s:12:\"neverssl.com\";s:15:\"\u0000*\u0000certificates\";O:29:\"Illuminate\\Support\\Collection\":1:{s:8:\"\u0000*\u0000items\";a:3:{i:0;
         ..."
      },
      ...
   },
   "site":{
      "id":1,
      ... /* see above */
   }
}
Was this page helpful to you? Feel free to reach out via support@ohdear.app or on Twitter via @OhDearApp if you have any other questions. We'd love to help!