{"openapi":"3.1.0","info":{"title":"Pinger API","version":"1.0.0","summary":"Site monitoring and one-off diagnostics.","description":"Two families of endpoint.\n\n**Tools** run a single diagnostic and return the result. They are\npublic: a key is optional, and raises the rate limit from 30 to 300\nrequests a minute while attributing the call to your account.\n\n**Sites** manage what Pinger monitors on your behalf. These require\na key, which authenticates an account rather than a person, so it\nkeeps working after whoever created it has gone."},"servers":[{"url":"https://api.pinger.ai"}],"tags":[{"name":"Tools","description":"One-off diagnostics. A key is optional."},{"name":"Sites","description":"The sites Pinger monitors for your account."},{"name":"Monitors","description":"Which checks run against a site."},{"name":"Incidents","description":"Outages Pinger opened and resolved."},{"name":"Account","description":"Who the calling credential belongs to."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key from the console, sent as `Authorization: Bearer pi_live_...`."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"Monitor":{"type":"object","properties":{"key":{"type":"string","enum":["http","ssl","dns","dns_propagation","whois","email_security","redirects","robots_txt","sitemap","safe_browsing","ai_crawlers","security_headers"]},"label":{"type":"string"},"description":{"type":"string"},"enabled":{"type":"boolean"},"on_demand":{"type":"boolean","description":"Whether POST /sites/{id}/checks can run it."}}},"Site":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string","examples":["example.com"]},"canonical_host":{"type":["string","null"],"description":"Where the site is actually served, once resolved."},"active":{"type":"boolean"},"status":{"type":"string"},"check_interval_minutes":{"type":"integer"},"alert_consecutive_failures":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"monitors":{"type":"array","items":{"$ref":"#/components/schemas/Monitor"}},"last_check":{"type":["object","null"]},"open_incident":{"type":["object","null"]}}},"Incident":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["open","resolved"]},"check_type":{"type":["string","null"]},"started_at":{"type":"string","format":"date-time"},"resolved_at":{"type":["string","null"],"format":"date-time"}}}}},"security":[{"bearerAuth":[]}],"paths":{"/v1/tools/http-headers":{"get":{"tags":["Tools"],"summary":"HTTP Headers","description":"Status code and response headers, without following redirects.","operationId":"tool_http_headers","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The url to check.","schema":{"type":"string","examples":["https://example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/ssl-checker":{"get":{"tags":["Tools"],"summary":"SSL Certificate","description":"Validity, expiry, issuer, chain, and the negotiated TLS version and cipher.","operationId":"tool_ssl_checker","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The domain to check.","schema":{"type":"string","examples":["example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/redirect-chain":{"get":{"tags":["Tools"],"summary":"Redirect Chain","description":"Every hop, with loops and dead hops identified.","operationId":"tool_redirect_chain","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The url to check.","schema":{"type":"string","examples":["http://example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/dns-lookup":{"get":{"tags":["Tools"],"summary":"DNS Lookup","description":"A, AAAA, MX, NS, TXT and CNAME records.","operationId":"tool_dns_lookup","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The domain to check.","schema":{"type":"string","examples":["example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/dns-propagation":{"get":{"tags":["Tools"],"summary":"DNS Propagation","description":"How a record has spread across public resolvers worldwide.","operationId":"tool_dns_propagation","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The domain to check.","schema":{"type":"string","examples":["example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/domain-expiry":{"get":{"tags":["Tools"],"summary":"Domain Expiry","description":"Registrar, registration dates and days remaining.","operationId":"tool_domain_expiry","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The domain to check.","schema":{"type":"string","examples":["example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/whois-lookup":{"get":{"tags":["Tools"],"summary":"WHOIS Lookup","description":"Registration data, registrar, nameservers and status.","operationId":"tool_whois_lookup","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The domain to check.","schema":{"type":"string","examples":["example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/email-security":{"get":{"tags":["Tools"],"summary":"SPF / DKIM / DMARC","description":"Email authentication records, including the DMARC policy.","operationId":"tool_email_security","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The domain to check.","schema":{"type":"string","examples":["example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/url-ping":{"get":{"tags":["Tools"],"summary":"URL Ping","description":"DNS, connect, TLS and time to first byte, sampled repeatedly.","operationId":"tool_url_ping","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The url to check.","schema":{"type":"string","examples":["https://example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/ai-crawlers":{"get":{"tags":["Tools"],"summary":"AI Crawler Check","description":"Resolved access for 28 AI and search crawlers.","operationId":"tool_ai_crawlers","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The domain to check.","schema":{"type":"string","examples":["example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/security-headers":{"get":{"tags":["Tools"],"summary":"Security Headers","description":"A weighted grade for the security headers a URL serves.","operationId":"tool_security_headers","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":true,"description":"The url to check.","schema":{"type":"string","examples":["https://example.com"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tools/what-is-my-ip":{"get":{"tags":["Tools"],"summary":"What Is My IP?","description":"Public IP address with network and location. The target is optional.","operationId":"tool_what_is_my_ip","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"target","in":"query","required":false,"description":"The ip to check. Defaults to the caller's own address.","schema":{"type":"string","examples":["104.26.10.74"]}}],"responses":{"200":{"description":"The check ran. The body is the result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"target was missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key was invalid, revoked or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The check could not complete. The target did not answer or returned something unusable. This is not a fault on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pinger/api/v1/me":{"get":{"tags":["Account"],"summary":"Who this credential is","operationId":"me","description":"Answers for both kinds of caller. A key identifies an account; a user token identifies a person.","responses":{"200":{"description":"The calling account.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No valid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pinger/api/v1/sites":{"get":{"tags":["Sites"],"summary":"List sites","operationId":"listSites","parameters":[{"name":"active","in":"query","required":false,"description":"Filter to active or deactivated sites.","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"maximum":100}}],"responses":{"200":{"description":"The account's sites.","content":{"application/json":{"schema":{"type":"object","properties":{"sites":{"type":"array","items":{"$ref":"#/components/schemas/Site"}},"count":{"type":"integer"}}}}}}}},"post":{"tags":["Sites"],"summary":"Register a site","operationId":"createSite","description":"Checks start immediately rather than waiting for the next scheduled run.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","examples":["example.com"]},"check_interval_minutes":{"type":"integer","default":5},"alert_consecutive_failures":{"type":"integer","default":2},"monitors":{"type":"object","description":"Monitors to enable or disable, by name.","additionalProperties":{"type":"boolean"},"examples":[{"sitemap":true,"dns":false}]}}}}}},"responses":{"201":{"description":"The site as registered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"401":{"description":"No valid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The domain was invalid, or already monitored by this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pinger/api/v1/sites/{id}":{"get":{"tags":["Sites"],"summary":"Read one site","operationId":"getSite","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"404":{"description":"No such site on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Sites"],"summary":"Update a site","operationId":"updateSite","description":"The domain cannot be changed: a different domain is a different site.","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"check_interval_minutes":{"type":"integer"},"alert_consecutive_failures":{"type":"integer"},"monitors":{"type":"object","additionalProperties":{"type":"boolean"}}}}}}},"responses":{"200":{"description":"The updated site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"404":{"description":"No such site on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The update was rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Sites"],"summary":"Deactivate a site","operationId":"deactivateSite","description":"Deactivation, never deletion. The check history stays attached and readable.","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The deactivated site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"404":{"description":"No such site on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pinger/api/v1/sites/{id}/reactivate":{"post":{"tags":["Sites"],"summary":"Reactivate a site","operationId":"reactivateSite","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The reactivated site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"404":{"description":"No such site on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pinger/api/v1/sites/{id}/monitors":{"get":{"tags":["Monitors"],"summary":"List a site's monitors","operationId":"listMonitors","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Every monitor, with whether it is on.","content":{"application/json":{"schema":{"type":"object","properties":{"site_id":{"type":"string","format":"uuid"},"monitors":{"type":"array","items":{"$ref":"#/components/schemas/Monitor"}}}}}}}}},"patch":{"tags":["Monitors"],"summary":"Turn monitors on or off","operationId":"updateMonitors","description":"Monitors not named are left alone. An unknown name is reported rather than ignored, and nothing is applied.","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["monitors"],"properties":{"monitors":{"type":"object","additionalProperties":{"type":"boolean"},"examples":[{"http":true,"ssl":true}]}}}}}},"responses":{"200":{"description":"The monitors as they now stand.","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No such site on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"One of the names is not a monitor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pinger/api/v1/sites/{id}/checks":{"post":{"tags":["Monitors"],"summary":"Run checks now","operationId":"runChecks","description":"Queues the work and returns. A probe takes seconds, so nothing runs inline.","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}},{"name":"monitor","in":"query","required":false,"description":"Run one monitor rather than every enabled one.","schema":{"type":"string","enum":["http","ssl","dns","whois","robots_txt","sitemap","safe_browsing","ai_crawlers","security_headers"]}}],"responses":{"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"site_id":{"type":"string","format":"uuid"},"queued":{"type":"array","items":{"type":"string"}}}}}}},"404":{"description":"No such site on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The site is deactivated, or the monitor is unknown, not enabled, or has no on-demand check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pinger/api/v1/sites/{id}/incidents":{"get":{"tags":["Incidents"],"summary":"A site's incidents","operationId":"listIncidents","parameters":[{"name":"id","in":"path","required":true,"description":"The site's uuid.","schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["open"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"maximum":100}}],"responses":{"200":{"description":"Incidents, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"site_id":{"type":"string","format":"uuid"},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/Incident"}}}}}}},"404":{"description":"No such site on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
