API Reference
Logging API: send logs, heartbeats and monitors to one endpoint
LogBlazer provides endpoints for ingesting logs, managing heartbeat monitors, and managing browser monitors. Send log data via POST and it appears in your dashboard. Register heartbeat URLs and LogBlazer will actively ping them on a schedule, tracking health checks, response times, and alerting you when things break. Register browser monitors and LogBlazer will load the page in a real browser and check what rendered against your own CSS selectors.
Last updated 2026-08-16
Base URL
https://app.logblazer.comLog ingestion endpoint
/api/logs/{api_key}The api_key is a UUID unique to each project. You can find it in your project settings on the LogBlazer dashboard. No other authentication is required — the key in the URL is your credential.
Request format
Headers
Content-Type: application/jsonBody (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
payload | string | Yes | The log message content. |
status | string | No | One of: SUCCESS, FAILURE, WARNING, NOTICE. Defaults to NOTICE. |
source | string | No | Identifies the origin of the log (e.g. web-server, cron-worker, deploy-script). Max 255 characters. |
monitor_title | string | No* | Display name for the monitor on your project dashboard (e.g. CPU Usage, Deploy Status). Max 255 characters. |
monitor_type | string | No* | One of: status, boolean, number, text. Determines how the value is displayed on the dashboard. |
monitor_value | string | No* | The current value for this monitor (e.g. healthy, true, 42). Max 255 characters. |
monitor_status | string | No | Controls the color tint of the monitor card. One of: success (green), failure (red), warning (yellow). Omit for a neutral appearance. |
monitor_meta | string | No | Free-form secondary info shown next to the monitor's timestamp on the dashboard card (e.g. 3m 30sec, 42 ms, v2.4.1). Often a duration but free-form. Max 255 characters. |
* Monitor fields are optional, but if any one is provided then all three (monitor_title, monitor_type, monitor_value) are required together.
Monitor cards
Monitors let you display the latest state of a value on your project dashboard. Each log entry can optionally include monitor data. The dashboard shows the most recent value for each unique monitor_title within a project.
Monitor types
| Type | Description |
|---|---|
status | A status label such as healthy, degraded, or down. |
boolean | A true/false value (e.g. true or false). |
number | A numeric value (e.g. 42, 99.8). |
text | Free-form text (e.g. v2.4.1, us-east-1). |
Monitor status (color)
The optional monitor_status field controls the color tint of the monitor card on the dashboard. It is independent of the log status field.
| Value | Color | Use when |
|---|---|---|
success | Green | Healthy, deployed, passed, OK |
failure | Red | Failed, error, down |
warning | Yellow | Degraded, slow, at capacity |
When omitted, the monitor card renders with a neutral appearance.
Example: sending a monitor
curl -X POST https://app.logblazer.com/api/logs/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"payload": "Health check passed",
"status": "SUCCESS",
"source": "health-checker",
"monitor_title": "API Status",
"monitor_type": "status",
"monitor_value": "healthy",
"monitor_status": "success",
"monitor_meta": "42 ms"
}'Responses
201 Created
{
"message": "Log received"
}404 Not Found
Returned when the API key does not match any project.
422 Unprocessable Entity
Returned when validation fails (e.g. missing payload or invalid status value).
Code examples
cURL
curl -X POST https://app.logblazer.com/api/logs/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{"payload": "User signed up", "status": "SUCCESS", "source": "auth-service"}'JavaScript (fetch)
await fetch("https://app.logblazer.com/api/logs/YOUR_API_KEY", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
payload: "Deployment finished",
status: "SUCCESS",
source: "deploy-script"
})
});PHP
$response = Http::post("https://app.logblazer.com/api/logs/YOUR_API_KEY", [
'payload' => 'Database backup completed',
'status' => 'SUCCESS',
'source' => 'backup-worker',
]);Python
import requests
requests.post("https://app.logblazer.com/api/logs/YOUR_API_KEY", json={
"payload": "Cron job failed: timeout after 30s",
"status": "FAILURE",
"source": "cron-worker"
})Bash (minimal)
# Minimum required — just the payload
curl -X POST https://app.logblazer.com/api/logs/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{"payload": "Something happened"}'LLM-friendly endpoint
Each project's public dashboard has a plain-text endpoint designed for LLM consumption. It returns the current monitors and recent logs as a Markdown document. Public dashboards and the rest of the surface area are covered on the features page.
/d/{api_key}/llmResponse
Returns text/plain Markdown with monitors table and recent log entries. No authentication required.
# My Project — Dashboard
Generated: 2026-03-05 14:30:00 UTC
## Monitors (2)
| Monitor | Value | Monitor Status | Updated |
|---|---|---|---|
| API Status | healthy | success | 2026-03-05 14:25:00 |
| Deploy | DEPLOYED | success | 2026-03-05 14:20:00 |
## Recent Logs (3)
| Time | Source | Status | Payload |
|---|---|---|---|
| 2026-03-05 14:25:00 | health-checker | SUCCESS | Health check passed |
| 2026-03-05 14:20:00 | deploy-pipeline | SUCCESS | Production deployed |
| 2026-03-05 14:15:00 | cron | NOTICE | Backup completed |Usage
curl https://app.logblazer.com/d/YOUR_API_KEY/llmUse this endpoint to give AI agents and LLMs access to your project's current status. The same public dashboard is also available as a web page at /d/{api_key}.
Heartbeat monitors (cron and worker health checks)
Heartbeats let LogBlazer actively monitor your services. Register a URL and LogBlazer will ping it on a configurable schedule, parse a standardized JSON health response, and alert you by email when checks fail. Results are integrated into your project dashboard as monitors and log entries automatically. For the why-you-would-want-this version, see cron and heartbeat monitoring, or the Healthchecks.io comparison.
Register a heartbeat
/api/heartbeats/{api_key}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the heartbeat (e.g. My App Production). Max 255 characters. |
short_name | string | No | Compact display name for dashboard cards (e.g. CE Prod). Max 50 characters. Falls back to name if not set. |
url | string | Yes | The health check URL to ping (e.g. https://myapp.com/api/heartbeat). Max 2048 characters. |
auth_token | string | No | Bearer token sent with each health check request. Stored encrypted. |
interval_minutes | integer | No | How often to ping, in minutes. Range: 1–60. Default: 3. |
timeout_seconds | integer | No | Request timeout. Range: 1–30. Default: 10. |
alert_emails | array | No | Email addresses to notify on failure. Max 5 addresses. |
alert_after_failures | integer | No | Consecutive failures before alerting. Range: 1–10. Default: 2. |
Response — 201 Created
{
"id": "uuid",
"name": "My App Production",
"short_name": null,
"url": "https://myapp.com/api/heartbeat",
"interval_minutes": 3,
"timeout_seconds": 10,
"alert_emails": ["ops@myapp.com"],
"alert_after_failures": 2,
"is_active": true,
"last_status": "UNKNOWN",
"created_at": "2026-03-09T12:00:00Z"
}Other heartbeat endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/heartbeats/{api_key} | List all heartbeats for the project. |
| PATCH | /api/heartbeats/{api_key}/{id} | Update a heartbeat (partial update). |
| DELETE | /api/heartbeats/{api_key}/{id} | Delete a heartbeat. Returns 204. |
| GET | /api/heartbeats/{api_key}/{id}/status | Get current status, checks, and recent results. |
| POST | /api/heartbeats/{api_key}/{id}/check | Trigger an immediate health check. |
Health check protocol
Your target application should respond to LogBlazer's health check requests with a JSON body containing an overall status and individual checks. LogBlazer sends a GET request with Accept: application/json and an optional Authorization: Bearer header if configured.
Expected response
{
"status": "PASS",
"checks": {
"database": {
"status": "PASS",
"ms": 3,
"detail": "SELECT 1 succeeded",
"label": "DB Connection"
},
"queue_health": {
"status": "PASS",
"detail": "No stale jobs"
},
"external_api": {
"status": "FAIL",
"ms": 5023,
"detail": "Timeout after 5s"
}
}
}| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | PASS or FAIL. Overall health status. |
checks | object | No | Map of check name → check result. When omitted, only the top-level status is used. |
checks.*.status | string | Yes | PASS or FAIL for each check. |
checks.*.ms | integer | No | Response time in milliseconds. |
checks.*.detail | string | No | Human-readable context. |
checks.*.label | string | No | Custom display name for this check. Overrides the auto-humanized check key on the dashboard. |
HTTP status codes
Return 200 when all checks pass and 503 when one or more checks fail. Any other status code, timeout, or connection error is treated as a complete failure.
Example: registering and checking a heartbeat
# Register a heartbeat
curl -X POST https://app.logblazer.com/api/heartbeats/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"name": "Production API",
"url": "https://myapp.com/api/heartbeat",
"interval_minutes": 5,
"alert_emails": ["ops@myapp.com"],
"alert_after_failures": 3
}'
# Check status
curl https://app.logblazer.com/api/heartbeats/YOUR_API_KEY/HEARTBEAT_ID/status
# Trigger an immediate check
curl -X POST https://app.logblazer.com/api/heartbeats/YOUR_API_KEY/HEARTBEAT_ID/checkHow it works
Automatic monitoring
LogBlazer pings your URL at the configured interval. Each check creates log entries and monitor cards on your dashboard automatically.
Smart alerting
Alerts are sent only after the configured number of consecutive failures. You also get a recovery notification when a heartbeat comes back up.
Browser monitors with CSS-selector assertions
Browser monitors load a page in a real Chromium browser and decide whether it is healthy by looking at what actually rendered. Register a URL and a set of CSS selectors and LogBlazer will run the check on a schedule, recording the outcome together with console errors, failed network requests, and a full-page screenshot when the check fails. Results are integrated into your project dashboard as monitors and log entries automatically, and repeated failures are emailed to you. See browser monitoring for worked examples of pass and fail selectors.
Pass and fail selectors
A browser check does not decide health from the HTTP status alone. Once the page has loaded, LogBlazer polls the rendered DOM — every frame on the page, not just the top document — until one of your selectors matches a visible element or the render budget runs out.
Pass selectors
Evidence the page rendered what it should — the pricing table, the logged-in nav, the search results. The first pass selector to become visible ends the check as PASS. At least one is required: a monitor with no pass selector could never report a pass, so the API rejects it with a 422.
Fail selectors
Evidence something went wrong — an error banner, a stack trace, a maintenance notice. Fail selectors are optional, and they are checked before pass selectors on every poll, so a visible fail selector ends the check as FAIL even when a pass selector is also on the page.
Order of evaluation for one check: a page that fails to load is a FAIL; an HTTP status outside 200–299 is a FAIL recorded without evaluating any selector; otherwise LogBlazer polls fail selectors then pass selectors, roughly ten times a second, until render_timeout_seconds elapses. Nothing matching by then is a FAIL with reason render_timeout.
Create a browser monitor
/api/browser-monitors/{api_key}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the monitor (e.g. Marketing Site). Max 255 characters. |
short_name | string | No | Compact display name for dashboard cards. Max 50 characters. Falls back to name if not set. |
url | string | Yes | The page to load in the browser (e.g. https://myapp.com/pricing). Max 2048 characters. |
selectors | array | Yes | The CSS selectors that decide pass or fail. Between 1 and 20 entries, at least one of which must be kind: "pass". Array order is the stored order. |
selectors.*.selector | string | Yes | A CSS selector, matched against every frame on the page. Max 1000 characters. |
selectors.*.kind | string | Yes | pass or fail. Any other value is rejected. |
selectors.*.label | string | No | Display name for this selector on the dashboard. Max 255 characters. |
interval_minutes | integer | No* | How often to run the check, in minutes. Range: 5–1440. Default: 5. |
render_timeout_seconds | integer | No* | How long to keep polling the page for a matching selector after it loads. Range: 5–60. Default: 30. |
alert_emails | array | No | Email addresses to notify on failure, in addition to the project owner. Max 5 addresses. |
alert_after_failures | integer | No* | Consecutive failures before alerting. Range: 1–10. Default: 2. |
is_active | boolean | No* | Whether the scheduler runs this monitor. Default: true. |
* These fields have server-side defaults. Omit the key to take the default, or send a value — but an explicit null is rejected with a 422 rather than falling back to the default.
Response — 201 Created
{
"browser_monitor": {
"id": "uuid",
"project_id": "uuid",
"name": "Marketing Site",
"short_name": "mkt",
"url": "https://myapp.com/pricing",
"interval_minutes": 15,
"render_timeout_seconds": 45,
"alert_emails": ["ops@myapp.com"],
"alert_after_failures": 3,
"consecutive_failures": 0,
"last_checked_at": null,
"last_status": "UNKNOWN",
"is_active": true,
"created_at": "2026-03-09T12:00:00Z",
"updated_at": "2026-03-09T12:00:00Z",
"is_stale": false,
"selectors": [
{
"id": "uuid",
"browser_monitor_id": "uuid",
"selector": "#pricing-table",
"kind": "pass",
"label": "Pricing table",
"position": 0,
"created_at": "2026-03-09T12:00:00Z",
"updated_at": "2026-03-09T12:00:00Z"
},
{
"id": "uuid",
"browser_monitor_id": "uuid",
"selector": ".error-banner",
"kind": "fail",
"label": "Error banner",
"position": 1,
"created_at": "2026-03-09T12:00:00Z",
"updated_at": "2026-03-09T12:00:00Z"
}
],
"latest_result": null
}
}Selector position is assigned from the array order, never taken from the request, and last_status stays UNKNOWN until the first check runs. is_stale is derived, not stored: it turns true when an active monitor has gone longer than twice its interval without a check.
Other browser monitor endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/browser-monitors/{api_key} | List all browser monitors for the project, newest first, each with its selectors and latest result. |
| PATCH | /api/browser-monitors/{api_key}/{id} | Update a browser monitor (partial update). |
| DELETE | /api/browser-monitors/{api_key}/{id} | Delete a browser monitor along with its selectors and results. Returns 204 with an empty body. |
| GET | /api/browser-monitors/{api_key}/{id}/status | Get the monitor, its latest result, and up to 100 recent results. |
| POST | /api/browser-monitors/{api_key}/{id}/check | Queue an immediate check. Returns 202. |
Every response other than the delete returns the monitor wrapped in a browser_monitor key; the list endpoint wraps its array in browser_monitors. A PATCH is a true partial update: omitted fields are left alone. selectors is the exception — supply it and it replaces the entire set, so selector ids are not stable across an update, and the replacement must still contain at least one pass selector. Omit selectors to leave them untouched.
Check results
Every check writes a result row. The status endpoint returns three keys — browser_monitor with its selectors, latest_result, and recent_results (up to 100, newest first). The list, create, update, and check responses embed the newest one as latest_result, which is null until a check has run.
{
"id": "uuid",
"browser_monitor_id": "uuid",
"status": "FAIL",
"error_reason": "fail_selector_matched",
"status_code": 200,
"matched_selector_id": "uuid",
"matched_frame_url": "https://myapp.com/pricing",
"duration_ms": 2318,
"console_errors": ["TypeError: undefined is not a function"],
"network_failures": [
{ "url": "https://myapp.com/api/plans", "status": 500, "method": "GET" }
],
"screenshot_path": "browser-monitor-screenshots/uuid/uuid.png",
"error_message": null,
"created_at": "2026-03-09T12:00:00Z"
}| Field | Type | Description |
|---|---|---|
status | string | PASS or FAIL. |
error_reason | string | Why the check failed. null on a pass. See the table above. |
status_code | integer | HTTP status of the main document response. null when navigation never completed. |
matched_selector_id | string | Id of the selector that ended the check, pass or fail. null when nothing matched. |
matched_frame_url | string | URL of the frame the matching element was found in — useful when the match came from an iframe. |
duration_ms | integer | Wall-clock time for the whole check. |
console_errors | array | Browser console messages of type error captured during the check. |
network_failures | array | Requests that returned a status of 400 or above, each as {url, status, method}. |
screenshot_path | string | Stored full-page screenshot, captured when a check fails after the page loaded. null on a pass, and on a failure where navigation never completed. |
error_message | string | Free-text detail for navigation and subprocess errors. null otherwise. |
Failure reasons
| error_reason | Meaning |
|---|---|
null | The check passed — a pass selector became visible. |
fail_selector_matched | A fail selector became visible. matched_selector_id identifies which one. |
render_timeout | No selector matched before render_timeout_seconds elapsed. |
http_status | The page responded with a status outside 200–299. Selectors are never evaluated. status_code carries the status. |
navigation_failed | The browser could not load the URL at all — DNS failure, refused connection, or navigation timeout. error_message carries the detail. |
subprocess_error | The browser process itself failed or exceeded its own timeout. error_message carries the detail. |
Example: creating and checking a browser monitor
# Create a browser monitor
curl -X POST https://app.logblazer.com/api/browser-monitors/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"name": "Marketing Site",
"url": "https://myapp.com/pricing",
"interval_minutes": 15,
"render_timeout_seconds": 45,
"alert_emails": ["ops@myapp.com"],
"alert_after_failures": 3,
"selectors": [
{ "selector": "#pricing-table", "kind": "pass", "label": "Pricing table" },
{ "selector": ".plan-card", "kind": "pass" },
{ "selector": ".error-banner", "kind": "fail", "label": "Error banner" }
]
}'
# Read current status, latest result, and recent results
curl https://app.logblazer.com/api/browser-monitors/YOUR_API_KEY/MONITOR_ID/status
# Queue an immediate check
curl -X POST https://app.logblazer.com/api/browser-monitors/YOUR_API_KEY/MONITOR_ID/checkHow it works
Checks are queued, not inline
A browser check holds a Chromium for tens of seconds, so it runs on a queue. The trigger endpoint returns 202 as soon as the job is queued — the latest_result in that response is still the previous run, so poll the status endpoint for the new one. Triggering a monitor that already has a check in flight is deduplicated.
Smart alerting
A down alert goes out when consecutive_failures reaches alert_after_failures, to the project owner plus every address in alert_emails. A recovery alert is sent only after a monitor that actually alerted comes back, so a single transient failure never produces a pair of emails.
Quick reference
Authentication
API key in the URL path. No headers or tokens needed.
Content type
Always application/json.
Status values
SUCCESS, FAILURE, WARNING, NOTICE
Monitor types
status, boolean, number, text
Monitor status
success, failure, warning
Rate limits
Browser monitor endpoints: 60 requests per minute. Log and heartbeat endpoints are unlimited.
Heartbeat intervals
1–60 minutes (default 3)
Health check response
200 = PASS, 503 = FAIL, other = failure
Browser monitor intervals
5–1440 minutes (default 5)
Selector kinds
pass, fail — at least one pass per monitor
Send your first log in under 60 seconds
Free forever plan, no credit card. One POST and it is on your dashboard.