update docs

This commit is contained in:
nate 2026-04-09 20:52:49 +04:00
parent 968887a8f4
commit 21194371b8
2 changed files with 172 additions and 4 deletions

View File

@ -60,6 +60,8 @@
<a href="#monitors" class="nav-link">Monitors</a>
<a href="#notifications" class="nav-link">Notifications</a>
<a href="#webhook-payload" class="nav-link">Webhook payload</a>
<a href="#status-pages" class="nav-link">Status Pages</a>
<a href="#incidents" class="nav-link">Incidents</a>
<div class="nav-section">Query Language</div>
<a href="#ql-fields" class="nav-link">Fields</a>
@ -340,6 +342,159 @@ Content-Type: application/json
<p>Always verify against the <em>raw</em> request body before parsing JSON.</p>
</div>
<!-- Status Pages -->
<div id="status-pages" class="section">
<h2>Status Pages</h2>
<p>Create public status pages that display live uptime, heartbeat bars, and incidents for your monitors. Each page gets a unique slug and is publicly accessible at <code>status.pingql.com/{slug}</code>.</p>
<h3>List pages</h3>
<div class="endpoint"><span class="method get">GET</span><span class="path">/status-pages</span></div>
<p class="endpoint-desc">Returns all status pages for the authenticated account.</p>
<h3>Create page</h3>
<div class="endpoint"><span class="method post">POST</span><span class="path">/status-pages</span></div>
<div class="cb">
<div class="cb-header"><span class="cb-lang">json — request body</span></div>
<pre>{
<span class="k">"slug"</span>: <span class="s">"my-app"</span>,
<span class="k">"title"</span>: <span class="s">"My App Status"</span>,
<span class="k">"groups"</span>: [
{ <span class="k">"name"</span>: <span class="s">"Core"</span>, <span class="k">"position"</span>: <span class="n">0</span> },
{ <span class="k">"name"</span>: <span class="s">"Integrations"</span>, <span class="k">"position"</span>: <span class="n">1</span> }
],
<span class="k">"monitors"</span>: [
{ <span class="k">"monitor_id"</span>: <span class="s">"a1b2c3d4e5f67890"</span>, <span class="k">"group_index"</span>: <span class="n">0</span> },
{ <span class="k">"monitor_id"</span>: <span class="s">"f0e1d2c3b4a59687"</span>, <span class="k">"group_index"</span>: <span class="n">1</span>, <span class="k">"display_name"</span>: <span class="s">"Stripe"</span> }
]
}</pre>
</div>
<table>
<thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
<tbody>
<tr><td>slug</td><td>string</td><td>URL slug (lowercase, hyphens, 1-80 chars). Must be unique.</td></tr>
<tr><td>title</td><td>string</td><td>Page title shown in the header (up to 200 chars).</td></tr>
<tr><td>description</td><td>string?</td><td>Shown below the title (up to 2000 chars).</td></tr>
<tr><td>theme</td><td>string?</td><td><code>auto</code>, <code>light</code>, or <code>dark</code>. Default <code>auto</code>.</td></tr>
<tr><td>password</td><td>string?</td><td>Plain text, hashed at write time. Pass <code>null</code> to clear.</td></tr>
<tr><td>display_mode</td><td>string?</td><td><code>compact</code> or <code>expanded</code>. Default <code>expanded</code>.</td></tr>
<tr><td>default_window</td><td>string?</td><td><code>24h</code>, <code>7d</code>, <code>30d</code>, or <code>90d</code>. Default <code>24h</code>.</td></tr>
<tr><td>bar_frequency</td><td>string?</td><td><code>hourly</code> or <code>daily</code>. Default <code>daily</code>.</td></tr>
<tr><td>bar_count</td><td>number?</td><td>How many bars to show (1-180). Default 90.</td></tr>
<tr><td>auto_refresh_s</td><td>number?</td><td>Auto-refresh interval in seconds (10-3600). Default 60.</td></tr>
<tr><td>custom_css</td><td>string?</td><td>Custom CSS injected after the default stylesheet (up to 50KB).</td></tr>
<tr><td>footer_text</td><td>string?</td><td>Text shown in the page footer (up to 5000 chars).</td></tr>
<tr><td>og_image_url</td><td>string?</td><td>OpenGraph image URL for social previews.</td></tr>
<tr><td>analytics_html</td><td>string?</td><td>Raw HTML injected in the head (e.g. analytics snippet).</td></tr>
<tr><td>index_search</td><td>boolean?</td><td>Allow search engine indexing. Default <code>true</code>.</td></tr>
<tr><td>show_powered_by</td><td>boolean?</td><td>Show "Powered by PingQL" footer. Default <code>true</code>.</td></tr>
<tr><td>show_response_time</td><td>boolean?</td><td>Display response time per monitor. Default <code>true</code>.</td></tr>
<tr><td>show_cert_expiry</td><td>boolean?</td><td>Show cert expiry info. Default <code>false</code>.</td></tr>
<tr><td>groups</td><td>array?</td><td>Groups to organize monitors. Each has <code>name</code> (string) and optional <code>position</code> (number).</td></tr>
<tr><td>monitors</td><td>array?</td><td>Monitors to display. See monitor fields below.</td></tr>
</tbody>
</table>
<h3>Monitor fields</h3>
<p>Each entry in the <code>monitors</code> array accepts:</p>
<table>
<thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
<tbody>
<tr><td>monitor_id</td><td>string</td><td>ID of a monitor you own.</td></tr>
<tr><td>group_index</td><td>number?</td><td>Index into the <code>groups</code> array (0-based). Omit for ungrouped.</td></tr>
<tr><td>display_name</td><td>string?</td><td>Override the monitor's name on this page.</td></tr>
<tr><td>display_mode</td><td>string?</td><td><code>compact</code> or <code>expanded</code>. Overrides the page default for this monitor.</td></tr>
<tr><td>position</td><td>number?</td><td>Sort order within the group.</td></tr>
</tbody>
</table>
<h3>Get page</h3>
<div class="endpoint"><span class="method get">GET</span><span class="path">/status-pages/:id</span></div>
<p class="endpoint-desc">Returns the page with its <code>groups</code> and <code>monitors</code> arrays, plus <code>has_password</code> (boolean).</p>
<h3>Update page</h3>
<div class="endpoint"><span class="method patch">PATCH</span><span class="path">/status-pages/:id</span></div>
<p class="endpoint-desc">All fields optional. If <code>groups</code> or <code>monitors</code> are provided, they replace the full set.</p>
<h3>Delete page</h3>
<div class="endpoint"><span class="method delete">DELETE</span><span class="path">/status-pages/:id</span></div>
<p class="endpoint-desc">Permanently removes the page and all associated groups and monitor links.</p>
<h3>Public endpoints</h3>
<p>Each published page is available at <code>status.pingql.com/{slug}</code> in multiple formats:</p>
<table>
<thead><tr><th>URL</th><th>Description</th></tr></thead>
<tbody>
<tr><td>/{slug}</td><td>HTML page with live uptime, bars, and incidents.</td></tr>
<tr><td>/{slug}.json</td><td>Full JSON payload (monitors, uptime, incidents).</td></tr>
<tr><td>/{slug}.rss</td><td>RSS feed of incidents.</td></tr>
<tr><td>/{slug}/badge.svg</td><td>Embeddable SVG status badge.</td></tr>
<tr><td>/{slug}/monitor/{id}.json</td><td>Per-monitor detail (uptime, regions, incidents).</td></tr>
</tbody>
</table>
<p>Password-protected pages return <code>404</code> for all formats unless a valid auth cookie is present. Post credentials via <code>POST /{slug}/auth</code> with a form-encoded <code>password</code> field.</p>
</div>
<!-- Incidents -->
<div id="incidents" class="section">
<h2>Incidents</h2>
<p>Declare incidents, post updates as the situation develops, and link them to monitors and status pages. Active incidents appear on any linked status page automatically.</p>
<h3>List incidents</h3>
<div class="endpoint"><span class="method get">GET</span><span class="path">/incidents</span></div>
<p class="endpoint-desc">Returns the 200 most recent incidents, newest first.</p>
<h3>Create incident</h3>
<div class="endpoint"><span class="method post">POST</span><span class="path">/incidents</span></div>
<div class="cb">
<div class="cb-header"><span class="cb-lang">json — request body</span></div>
<pre>{
<span class="k">"title"</span>: <span class="s">"API returning 503s"</span>,
<span class="k">"status"</span>: <span class="s">"investigating"</span>,
<span class="k">"severity"</span>: <span class="s">"major"</span>,
<span class="k">"monitor_ids"</span>: [<span class="s">"a1b2c3d4e5f67890"</span>],
<span class="k">"status_page_ids"</span>: [<span class="s">"f8c1a2b3-..."</span>],
<span class="k">"initial_update"</span>: {
<span class="k">"body"</span>: <span class="s">"We're seeing elevated error rates on the API. Investigating now."</span>
}
}</pre>
</div>
<table>
<thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
<tbody>
<tr><td>title</td><td>string</td><td>Short description (up to 200 chars).</td></tr>
<tr><td>status</td><td>string</td><td><code>investigating</code>, <code>identified</code>, <code>monitoring</code>, or <code>resolved</code>.</td></tr>
<tr><td>severity</td><td>string?</td><td><code>minor</code>, <code>major</code>, or <code>critical</code>. Default <code>minor</code>.</td></tr>
<tr><td>pinned</td><td>boolean?</td><td>Pinned incidents show in the active section on status pages. Default <code>true</code>.</td></tr>
<tr><td>monitor_ids</td><td>array?</td><td>IDs of affected monitors.</td></tr>
<tr><td>status_page_ids</td><td>array?</td><td>IDs of status pages to display this incident on.</td></tr>
<tr><td>initial_update</td><td>object?</td><td>Create the first timeline update along with the incident. Has one field: <code>body</code> (string, supports basic markdown).</td></tr>
</tbody>
</table>
<h3>Get incident</h3>
<div class="endpoint"><span class="method get">GET</span><span class="path">/incidents/:id</span></div>
<p class="endpoint-desc">Returns the incident with its <code>updates</code> timeline, <code>monitor_ids</code>, and <code>status_page_ids</code>.</p>
<h3>Update incident</h3>
<div class="endpoint"><span class="method patch">PATCH</span><span class="path">/incidents/:id</span></div>
<p class="endpoint-desc">All fields optional. Setting status to <code>resolved</code> automatically sets <code>resolved_at</code>. Changing to any other status clears it.</p>
<h3>Post update</h3>
<div class="endpoint"><span class="method post">POST</span><span class="path">/incidents/:id/updates</span></div>
<div class="cb">
<div class="cb-header"><span class="cb-lang">json — request body</span></div>
<pre>{
<span class="k">"status"</span>: <span class="s">"identified"</span>,
<span class="k">"body"</span>: <span class="s">"Root cause identified — a bad deploy at 14:02 UTC. Rolling back now."</span>
}</pre>
</div>
<p>The <code>body</code> field supports basic markdown: <code>**bold**</code>, <code>*italic*</code>, <code>`code`</code>, and <code>[links](url)</code>. The incident's status is automatically synced to the latest update's status.</p>
<h3>Delete incident</h3>
<div class="endpoint"><span class="method delete">DELETE</span><span class="path">/incidents/:id</span></div>
<p class="endpoint-desc">Permanently removes the incident, all its updates, and all monitor/page links.</p>
</div>
<!-- QL Fields -->
<div id="ql-fields" class="section">
<h2>Query Language — Fields</h2>

View File

@ -552,18 +552,31 @@
</div>
<div class="grid lg:grid-cols-2 gap-6">
<!-- Create account -->
<!-- Create status page -->
<div class="terminal">
<div class="terminal-bar">
<div class="terminal-dot bg-[#ff5f57]"></div>
<div class="terminal-dot bg-[#ffbd2e]"></div>
<div class="terminal-dot bg-[#28c840]"></div>
<span class="ml-3 text-xs text-gray-500 font-mono">Create an account</span>
<span class="ml-3 text-xs text-gray-500 font-mono">Create a status page</span>
</div>
<div class="terminal-body text-xs sm:text-[13px]">
<pre><span class="text-gray-500">$</span> <span class="text-white">curl</span> -X POST https://pingql.com/api/register
<pre><span class="text-gray-500">$</span> <span class="text-white">curl</span> -X POST https://pingql.com/api/status-pages \
-H <span class="syn-str">"X-Key: abcd-1234-efgh-5678"</span> \
-d <span class="syn-str">'{
"slug": "my-app",
"title": "My App Status",
"monitors": [
{ "monitor_id": "a1b2c3d4e5f67890" }
]
}'</span>
<span class="syn-brace">{</span> <span class="syn-key">"key"</span>: <span class="syn-str">"abcd-1234-efgh-5678"</span> <span class="syn-brace">}</span></pre>
<span class="syn-brace">{</span>
<span class="syn-key">"id"</span>: <span class="syn-str">"f8c1a2b3-..."</span>,
<span class="syn-key">"slug"</span>: <span class="syn-str">"my-app"</span>,
<span class="syn-key">"title"</span>: <span class="syn-str">"My App Status"</span>,
<span class="syn-key">"theme"</span>: <span class="syn-str">"auto"</span>
<span class="syn-brace">}</span></pre>
</div>
</div>