' + 'Account & API keys' + 'Sign out'; panel.querySelector('#seoSignOut').addEventListener('click', function (e) { e.preventDefault(); signOut(); }); } else { label.hidden = true; var redir = encodeURIComponent(location.href); panel.innerHTML = '
' + (mode === 'login' ? 'Sign in' : 'Create a free account') + '
' + '
' + 'Continue with Google' + 'Facebook' + '
' + '
or
' + '' + '
' + '' + '' + '' + '
' + '

' + (mode === 'login' ? 'New here? Create a free account · Forgot password?' : 'Have an account? Sign in') + '

'; panel.querySelector('#seoAuthToggle').addEventListener('click', function () { mode = mode === 'login' ? 'register' : 'login'; render(); var f = panel.querySelector('input'); if (f) f.focus(); }); panel.querySelector('#seoAuthForm').addEventListener('submit', submit); } } function submit(e) { e.preventDefault(); var form = e.target, email = form.email.value.trim(), password = form.password.value; var err = panel.querySelector('#seoAuthErr'), sbtn = form.querySelector('.seo-auth-btn'); var labelTxt = mode === 'login' ? 'Sign in' : 'Create account'; err.style.display = 'none'; sbtn.disabled = true; sbtn.textContent = '…'; fetch(apiBase + (mode === 'login' ? '/api/auth/login' : '/api/auth/register'), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email, password: password }), }) .then(function (r) { return r.json().then(function (d) { return { ok: r.ok, d: d }; }); }) .then(function (res) { if (!res.ok || !res.d.token) { err.textContent = res.d.error || res.d.message || 'Something went wrong. Try again.'; err.style.display = 'block'; sbtn.disabled = false; sbtn.textContent = labelTxt; return; } setToken(res.d.token); location.reload(); }) .catch(function () { err.textContent = 'Network error. Try again.'; err.style.display = 'block'; sbtn.disabled = false; sbtn.textContent = labelTxt; }); } function signOut() { var t = token(); setToken(null); if (t) fetch(apiBase + '/api/auth/logout', { method: 'POST', headers: { 'Authorization': 'Bearer ' + t } }).catch(function () {}); location.reload(); } window.erstatAuth = { open: openPanel, close: closePanel }; // Consume an OAuth return (?token / ?error) on any SEO page. try { var p = new URLSearchParams(location.search), tk = p.get('token'), er = p.get('error'); if (tk) { setToken(tk); history.replaceState({}, '', location.pathname + location.hash); } else if (er) { window.__erstatOAuthError = 'Sign-in failed: ' + er; history.replaceState({}, '', location.pathname + location.hash); } } catch (e) {} var t = token(); if (t) { fetch(apiBase + '/api/auth/me', { headers: { 'Authorization': 'Bearer ' + t } }) .then(function (r) { if (!r.ok) throw 0; return r.json(); }) .then(function (d) { user = d.user || d; if (!panel.hidden) render(); else { label.hidden = false; label.textContent = user.display_name || user.email || 'Account'; } }) .catch(function () { setToken(null); user = null; }); } })();

Embed a live ER status widget on your site

A free embed showing live emergency-room closures, reopenings and disruptions — for your newsroom, municipal page, or community group. Mobile-first, light & dark, auto-updating, no account.

Free for personal & non-commercial use with attribution. Building a commercial product? See data licensing. Prefer raw data? Grab a free key for the JSON API · RSS.

Live preview

Why embed live ER status?

When an emergency department closes overnight or diverts ambulances, the people who need that information are local. A widget on a community news site or a town's homepage puts real-time ER access right where residents already look — and it keeps itself current without anyone having to update it.

How it works

  1. Pick a region, theme, and how many updates to show.
  2. Copy the iframe snippet (works almost anywhere) or the JavaScript snippet (auto-resizes, more native).
  3. Paste it into your page's HTML. It updates itself from then on.

The widget itself needs no API key — just paste and go.

Want the raw data? Use the API

For building your own display or pulling ER status into another system, use the JSON API. It needs a free API key (the widget above does not) — create one in your account and send it as an X-API-Key header (or ?key=):

curl -H "X-API-Key: YOUR_KEY" \
  https://erstat.ca/api/v1/closures

Frequently asked questions

Is the ERstat widget free?

Yes. The embed is completely free for any site — newsrooms, municipal and health-authority pages, community groups, and personal sites. No account, no API key, no attribution fee.

What does the widget show?

A live, auto-updating list of emergency-room closures, reopenings and service disruptions for Canada or a province you choose. Data refreshes automatically and matches what you see on erstat.ca/feed.

Will it match my site’s design?

Set the theme to Auto and the widget follows your visitors’ light or dark preference, or pick Light or Dark explicitly. It is mobile-first and fluid from about 280px wide up to full width.

iframe or JavaScript — which should I use?

The iframe works on virtually any platform (WordPress, Wix, Squarespace, news CMSs) and is the safest choice. The JavaScript embed auto-resizes to its content and looks more native, but needs a site that allows third-party <script> tags. Both include a link back to ERstat.

Can I get the raw data instead?

Yes. Use the JSON API — it needs a free API key you create in your account — or the RSS feed (no key) if you just want a simple list. The widget itself never needs a key.

Can I use the widget or data in a commercial product?

The embed and free API are for non-commercial use with attribution. Commercial use — plus historical and bulk data, an uptime SLA, higher limits and webhooks — is available under a commercial license. See the data licensing page.