Documentation
Connect your website to MySentry
Everything MySentry accepts is one HTTPS request away: an error, a heartbeat, a page view. This page is the complete contract — the same one the WordPress plugin uses.
Quick start
- Create a website (project) in the panel. Copy the reporting URL it shows — it is shown once.
- WordPress: install the plugin and paste the URL. Any other site: set the uptime URL in the panel and, optionally, add the browser snippet and the analytics beacon below.
- Add your site’s origin (for example
https://www.example.com) to the panel’s allowed origins — required for browser errors and analytics, which are accepted only from those origins. - Paste a Slack incoming-webhook URL in the project settings and/or install MySentry as an app on your phone and enable notifications.
Reporting URL and keys
Every website has a reporting URL of the form
https://www.mysentry.co.uk/api/ingest/<site-slug>/<key>The same key works in two places: in the URL path (for browsers and simple integrations) or as a Bearer token in the Authorization header (recommended server-side, so the key never appears in proxy logs). A key can only submit events to its own website; it cannot read anything. Only a SHA-256 hash of the key is stored. You can hold two active keys for zero-downtime rotation and revoke a key instantly in the panel.
Reporting errors
POST https://www.mysentry.co.uk/api/ingest/error
Authorization: Bearer <key>
Content-Type: application/json
{
"context": "email.magicLink", // required, ≤120 chars — groups errors
"message": "SMTP connect timed out", // required, ≤2000 chars
"stack": "Error: ...\n at ...", // optional, ≤8000 chars
"level": "error", // fatal | error | warning | info | debug
"url": "https://app.example/login", // optional, ≤1000 chars
"app_version": "1.4.2", // optional, ≤40 chars
"env": "production", // production | preview | development
"meta": { "php": "8.3", "method": "POST" } // optional, ≤30 scalar keys
}The server fingerprints the event from context and the normalised message, masks email addresses and phone numbers in every text field, increments the count if the fingerprint is known (keeping the latest 30 occurrences) or creates a new error — and alerts on a new fingerprint or a regression. Pick contexts the way you would name log channels: email.*, payments.*, client.*. Events under email.* feed the failed-email burst rule.
Response 202 means accepted. Nothing is returned about the stored event.
Browser errors from any site
Browser reports use the reporting URL directly and are accepted only from allowed origins (CORS). A minimal reporter — add your URL and keep it below 10 reports per page load to stay within the per-IP limit:
<script>
(function () {
var url = "https://www.mysentry.co.uk/api/ingest/<site-slug>/<key>";
var sent = 0;
function report(message, stack) {
if (sent++ >= 10) return;
try {
fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
context: "client.js",
message: String(message).slice(0, 2000),
stack: stack ? String(stack).slice(0, 8000) : null,
level: "error",
url: location.href,
meta: { ua: navigator.userAgent.slice(0, 200) }
}),
keepalive: true
});
} catch (e) {}
}
window.addEventListener("error", function (e) {
report(e.message, e.error && e.error.stack);
});
window.addEventListener("unhandledrejection", function (e) {
var r = e.reason || {};
report(r.message || String(r), r.stack);
});
})();
</script>Cron heartbeats
POST https://www.mysentry.co.uk/api/ingest/heartbeat
Authorization: Bearer <key>
Content-Type: application/json
{ "monitor": "nightly-backup", "ok": true, "processed": 1240 }
# optional: let the job own its silence threshold (5–20160 minutes)
{ "monitor": "queue-worker", "ok": true, "threshold_minutes": 15 }The first heartbeat creates the monitor (default silence threshold 26 hours). Monitor names may contain letters, digits, dots, underscores and dashes, up to 80 characters. To catch a job that never starts, create an expected monitor in the panel first; its silence is counted from creation.
# shell
curl -s -X POST https://www.mysentry.co.uk/api/ingest/heartbeat \
-H "Authorization: Bearer $MYSENTRY_KEY" -H "Content-Type: application/json" \
-d '{"monitor":"nightly-backup","ok":true}'
# Node / Next.js (fire-and-forget)
fetch("https://www.mysentry.co.uk/api/ingest/heartbeat", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.MYSENTRY_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ monitor: "purge-trash", ok: true, processed: n }),
}).catch(() => {});Uptime and content checks
Configured in the panel, not by API: the URL to check, the interval (1–60 minutes, default 5) and an optional expected phrase. Checks are plain GET requests with the user agent MySentry-Uptime/1.0 and a 10-second timeout. If your firewall or WAF needs to allow-list the monitor, MySentry can send a secret header with every check — ask us for the header name and value for your account.
Analytics beacon
<script src="https://www.mysentry.co.uk/a.js"
data-endpoint="https://www.mysentry.co.uk/api/ingest/<site-slug>/<key>/collect"
defer></script>The script sends one page-view beacon per page and one engagement beacon when the page is hidden, via navigator.sendBeacon. Accepted only from allowed origins. The server derives the country from the network edge and counts unique visitors with a daily-rotating hash; no IP address or cookie is ever stored.
WordPress plugin
Install steps, what each context means and the heartbeat settings are on the WordPress page. The plugin speaks exactly this API: errors under wp.php.fatal, wp.php.warning, wp.client, email.wp_mail, wp.test; a heartbeat named after the site; and the analytics beacon.
Alert rules
- New error — immediately, once per fingerprint.
- Regression — immediately, when a resolved fingerprint recurs.
- Failed-email burst — once per 10-minute window when ≥3
email.*events fail. - Site down — on the second consecutive failed check, once per outage.
- Content mismatch — on the second consecutive check without the expected phrase, once per incident.
- Silent cron — once per monitor per day while silence exceeds the threshold; a distinct never started alert for expected monitors.
Channels: email to every member of the account (switchable per person), Slack incoming webhook (mutable per site for 1 h / 8 h / 24 h / indefinitely) and web push to every member. Recovery — site back up, content restored — is sent once on the same channels with the length of the incident.
Limits and responses
| Body size | 32 KB |
| Server-side rate | 600 events / minute / key |
| Browser rate | 30 events / minute / IP |
| message / stack / url | 2,000 / 8,000 / 1,000 characters (truncated, not rejected) |
| meta | ≤30 keys; string values ≤500 chars; numbers, booleans, null |
| Samples kept per error | 30 most recent |
| Bin retention | 30 days, then deleted |
Responses: 202 accepted · 400 invalid body · 401 unknown or revoked key · 403 origin not allowed (browser) · 413 body too large · 429 rate limited. Reporters should treat every response as fire-and-forget: monitoring must never break the application it watches.
Developer questions
How are my reporting keys protected?
A reporting key is shown exactly once when it is created; only a SHA-256 hash of it is stored, so it cannot be read back even by us. A key can only submit events to its own website — it cannot read anything. You can hold two active keys at a time to rotate without downtime, and revoke one instantly.
Can I send errors from a custom application?
Yes. Send a JSON POST with your key as a Bearer token: context, message and optionally stack, level, url, app_version, env and a small metadata object. The API answers 202 when the event is accepted and fingerprints, groups and alerts exactly as it does for WordPress. Libraries are not required — it is one HTTP request.
How do I send a heartbeat from any cron job?
Add one line at the end of the job: a POST to the heartbeat endpoint with the monitor name and whether it succeeded — a curl command is all it takes. The first heartbeat creates the monitor; the panel then lets you set how long a silence is acceptable.
What are the rate limits?
600 events per minute per reporting key for server-side reporters, 30 per minute per IP address for browser reporters, and a 32 KB request body. Messages are capped at 2,000 characters and stack traces at 8,000; anything longer is truncated, not rejected.
Can I report JavaScript errors from a site that is not WordPress?
Yes. Add a short snippet that listens for window errors and unhandled promise rejections and posts them to your reporting URL. Browser reports are accepted only from the origins you allow in the panel (CORS), so a copied key cannot be used from another site.
Get a reporting key
MySentry is in early access. Leave your email and you’ll get an invitation with founder pricing.
No spam, one email, unsubscribe any time.