Introduction
API documentation for Linked Wellness, including the V2 embedded-delivery SSO endpoints used by partner integrations.
Overview
Linked Wellness provides financial wellbeing tools (health checks, budgeting, savings and mortgage planning) delivered under each partner's own domain and branding. The V2 Partner SSO API lets your platform sign an already-authenticated member of yours straight into their Linked Wellness account — no separate password, no registration form — so the product feels like a native part of your platform. The V1 Content API provides read-only access to published content for your environment.
Authentication
The two API surfaces authenticate differently — don't mix them up:
| Surface | Mechanism | Where |
|---|---|---|
V2 Partner SSO (/api/v2/partners/{partner}/sso) |
Signed JWT assertion in the request body, HS256 with your shared secret | Your backend only — the secret must never reach a browser or mobile client |
V1 Content (/api/data, /api/content/...) |
API key, sent as an X-API-Key header (preferred) or api_key query parameter |
Your backend |
The SSO handoff deliberately does not use the API key: the signed assertion itself proves both who you are (only you hold the secret) and which member is being signed in.
Partner onboarding
During onboarding we issue you three things:
- Partner slug — your identifier in SSO URLs (the
{partner}path segment). - Shared signing secret — for HS256-signing assertions. Delivered over a secure channel, never email or chat. Store it server-side (a secrets manager or environment variable); never commit it or ship it to clients. To rotate it, contact us and we coordinate a cutover — assertions signed with the old secret stop verifying the moment the new one is live.
- API key — for the V1 Content API, if your integration uses it. Sent the same secure way.
You also tell us which of your environments (staging, production) should map to which of ours.
The SSO flow
Member's browser Your backend Linked Wellness
──────────────── ──────────── ───────────────
1. opens embedded ───► 2. mint HS256 JWT
wellbeing tab (sub, email, name,
iat, exp, jti)
│
│ POST /api/v2/partners/{partner}/sso
├────────────────────────────────────► 3. verify signature,
│ freshness, jti;
│ match/create member
│◄──────────────────────────────────── 4. 200 { consume_url }
│
5. browser redirected ◄──────────┘
to consume_url
│
│ GET /partner-sso/consume?token=...
├──────────────────────────────────────────────────────────► 6. validate one-time
│ token, set session
│◄────────────────────────────────────────────────────────── 7. 302 → /dashboard
▼
8. member is signed in on their dashboard
Steps 2–4 are server-to-server. Steps 5–7 happen in the member's browser. The whole flow typically completes in under a second; the consume URL expires 60 seconds after issue and is single-use, so redirect the browser immediately after receiving it.
JWT assertion requirements
- Algorithm: HS256, signed with your shared secret (a 64-character random string; note
HS256 requires keys of at least 32 bytes, and some JWT libraries enforce this). The
algheader must beHS256. iat/exp: Unix timestamps in seconds (not milliseconds), UTC. Assertions are rejected wheniatis older than 90 seconds, regardless ofexp. We tolerate up to 30 seconds of clock difference onexp/nbf— keep your servers on NTP.- Claims:
| Claim | Required | Type | Purpose |
|---|---|---|---|
sub |
yes | string | Your stable, unique member ID. The primary matching key — must never change or be reused for a different person. |
iat |
yes | integer | Issued-at, Unix seconds. Mint immediately before posting. |
exp |
yes | integer | Expiry, Unix seconds. Keep it short (e.g. iat + 90). |
jti |
yes | string | Unique ID per assertion (e.g. a UUID). Single-use — see replay handling. |
email |
recommended | string | Used to match an existing account and for support correlation. |
name |
optional | string | Display name for personalisation. |
Send nothing else — no addresses, dates of birth, or financial data. The claim set is deliberately minimal.
Replay handling
Every accepted jti is remembered for the 90-second assertion window; presenting the same
jti again returns 401 assertion_replayed. Because anything with an iat older than 90
seconds is rejected outright, this fully covers the replay window — an attacker who captures
an assertion in transit cannot reuse it. Mint a fresh assertion with a fresh jti for
every handoff, including retries: if a request times out, do not re-post the same token.
The consume URL has its own, separate single-use token (60-second lifetime), so a leaked or logged consume URL also cannot be replayed.
Error catalog
All V2 error bodies carry a stable error code and a human-readable message:
| HTTP | error code |
Meaning | What to do |
|---|---|---|---|
| 401 | invalid_assertion |
Signature check failed or token malformed | Verify you sign with the exact shared secret, HS256, compact JWS format |
| 401 | assertion_expired |
iat older than 90s, missing, or exp passed |
Mint the assertion immediately before the POST; check server clocks (NTP) |
| 401 | assertion_replayed |
jti already used |
Generate a fresh jti per handoff, including on retries |
| 401 | missing_claim |
A required claim (sub, jti) is absent |
Include all required claims |
| 403 | integration_disabled |
Your integration is switched off on our side | Contact support |
| 404 | unknown_partner |
The {partner} slug isn't recognised |
Check the slug from onboarding; note it's environment-specific |
| 422 | — | Request body invalid (e.g. assertion field missing) |
Standard Laravel validation body with an errors map |
| 429 | — | More than 30 handoff requests per minute per IP | Back off and respect the Retry-After header |
| 503 | integration_not_configured |
Our side is mid-setup for your integration | Contact us; nothing to fix on yours |
V1 Content API errors: 401 with a JSON message when the API key is missing or invalid,
404 when content is not found, 403 on the write endpoints (the API is read-only).
Security notes
- Token lifetimes: assertions ≤ 90 seconds from
iat; consume URLs 60 seconds, single-use. - Tenant scoping: an assertion for your partner slug can only ever create or access members inside your own environment — cross-partner access is structurally impossible.
- Transport: HTTPS only; plain HTTP is redirected. Send the assertion in the POST body, never in a URL, so it can't land in access logs.
- Secret handling: backend only, secrets manager or env var, rotate by coordinated cutover.
- What we store: the member's
sub,email,nameand the product data they generate while using Linked Wellness. Nothing flows back to your platform automatically.
Versioning and change policy
- The version is in the path (
/api/v2/...). Within a version, changes are additive only: new endpoints, new optional fields, new error codes. Consume responses ignore unknown JSON fields safely. - Breaking changes (removed/renamed fields, changed semantics, new required claims) only ship under a new version prefix. We give partners at least 90 days' written notice before retiring a version, and V1 remains available as documented for existing consumers.
- The changelog for this documentation is shared through your integration contact.
Authenticating requests
To authenticate requests, include a X-API-Key header with the value "{YOUR_API_KEY}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
API keys are issued during integration onboarding — contact us to receive yours. Send the key with every request, either as an X-API-Key header (preferred) or an api_key query parameter.
V2 - Partner SSO
Server-to-server handoff that signs a member of your platform into their Linked Wellness account without a password or registration form.
Sequence:
- A member opens the embedded wellbeing product inside your platform.
- Your backend mints a short-lived HS256 JWT assertion and POSTs it to the handoff endpoint below. Never do this from the browser — the shared secret must not leave your servers.
- We verify the assertion, create or match the member's account, and return a
single-use
consume_url(valid for 60 seconds). - Your platform redirects the member's browser (top-level or iframe) to that
consume_url. That request sets the session cookie and lands them on their dashboard — no further action from your side.
All error responses include a stable machine-readable error code (see the
Error catalog in the introduction) alongside a human-readable message.
Verify a member assertion and issue a one-time consume URL.
Rate limited to 30 requests per minute per IP; expect 429 Too Many Requests
with a Retry-After header beyond that.
Example request:
curl --request POST \
"https://api.linkedwellness.ie/api/v2/partners/acme/sso" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"assertion\": \"eyJhbGciOiJIUzI1NiJ9...\"
}"
const url = new URL(
"https://api.linkedwellness.ie/api/v2/partners/acme/sso"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"assertion": "eyJhbGciOiJIUzI1NiJ9..."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Assertion accepted):
{
"consume_url": "https://example.linkedwellness.ie/partner-sso/consume?token=Xy82jbqT..."
}
Example response (401, Bad signature or malformed token):
{
"error": "invalid_assertion",
"message": "The assertion signature is invalid or the token is malformed. Check the shared secret and HS256 signing."
}
Example response (401, Assertion too old (iat/exp)):
{
"error": "assertion_expired",
"message": "The assertion iat is missing or older than 90 seconds. Mint assertions immediately before posting them."
}
Example response (401, jti reused):
{
"error": "assertion_replayed",
"message": "This assertion jti has already been used. Mint a new assertion with a fresh jti for every handoff."
}
Example response (403, Integration disabled):
{
"error": "integration_disabled",
"message": "This partner integration is currently disabled. Contact support."
}
Example response (404, Unknown partner slug):
{
"error": "unknown_partner",
"message": "Unknown partner \"acme\"."
}
Example response (422, Missing assertion field):
{
"message": "The assertion field is required.",
"errors": {
"assertion": [
"The assertion field is required."
]
}
}
Example response (429, Rate limited):
{
"message": "Too Many Attempts."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Consume a one-time sign-in link (browser navigation).
This is the URL returned by the handoff endpoint. It is not an API call:
redirect the member's browser (top-level or iframe) to it as-is. It always
responds with a 302 redirect and never returns JSON.
Behavior:
- Valid token — the member's session is established (cookie set for the
tenant domain) and the browser is redirected to
/dashboard. On their very first visit they may be asked to pick a life stage before the dashboard. - Expired, reused, or unknown token — redirected to the login page with a friendly "sign-in link has expired" notice. Tokens are single-use and expire 60 seconds after issue, so redirect promptly and never cache or reuse a consume URL; recover by requesting a fresh handoff.
Example request:
curl --request GET \
--get "https://api.linkedwellness.ie/partner-sso/consume?token=Xy82jbqT..." \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://api.linkedwellness.ie/partner-sso/consume"
);
const params = {
"token": "Xy82jbqT...",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (302, Valid token: session established, redirect to /dashboard):
{}
Example response (302, Expired/reused token: redirect to /login with an explanatory notice):
{}
Example response (503):
Show headers
retry-after: 60
cache-control: no-cache, private
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="60">
<title>Under maintenance - Linked Wellness</title>
<style>
* { box-sizing: border-box; }
:root {
--primary: #165d65;
--accent: #00b08b;
--background-start: #effcf9;
--background-end: #d9f7f0;
--surface: #ffffff;
--text: #0f172a;
--muted: #475569;
--border: rgba(15, 23, 42, 0.08);
}
body {
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--text);
background:
radial-gradient(circle at top, rgba(255, 255, 255, 0.95), transparent 35%),
linear-gradient(135deg, var(--background-start), var(--background-end));
-webkit-font-smoothing: antialiased;
}
.card {
width: 100%;
max-width: 34rem;
border-radius: 1.5rem;
border: 1px solid var(--border);
background: var(--surface);
padding: 2rem;
text-align: center;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
}
.logo-wrap {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
}
.logo {
display: block;
max-width: min(100%, 16rem);
max-height: 4rem;
width: auto;
height: auto;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 9999px;
padding: 0.45rem 0.85rem;
background: color-mix(in srgb, var(--accent) 10%, white);
color: var(--primary);
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
}
h1 {
margin: 1.25rem 0 0.75rem;
color: var(--primary);
font-size: clamp(1.75rem, 4vw, 2.35rem);
line-height: 1.15;
}
p {
margin: 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.7;
}
.retry {
margin-top: 1.25rem;
color: var(--primary);
font-size: 0.9375rem;
font-weight: 600;
}
.maintenance-progress-wrap {
margin-top: 1.5rem;
text-align: left;
}
.maintenance-progress-label {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.75rem;
margin-bottom: 0.5rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-progress-label strong {
color: var(--primary);
font-weight: 700;
}
.maintenance-track {
height: 0.5rem;
border-radius: 9999px;
background: color-mix(in srgb, var(--primary) 10%, white);
overflow: hidden;
}
.maintenance-bar {
height: 100%;
width: 0%;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
transition: width 0.25s linear;
}
.maintenance-eta {
margin-top: 0.75rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-eta strong {
color: var(--text);
font-weight: 600;
}
.maintenance-eta-local {
color: var(--muted);
font-weight: 400;
}
.divider {
width: 4rem;
height: 0.25rem;
margin: 1.25rem auto 1.5rem;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
}
@media (max-width: 640px) {
.card {
padding: 1.5rem;
border-radius: 1.25rem;
}
.logo {
max-width: 12rem;
max-height: 3.25rem;
}
}
</style>
</head>
<body>
<div class="card">
<div class="logo-wrap">
<img class="logo" src="/images/Linked_Wellness_Logo_CMYK_Colour_Positive_Horizontal.svg" alt="Linked Wellness">
</div>
<div class="eyebrow">Scheduled maintenance</div>
<h1>We’ll be back shortly</h1>
<div class="divider"></div>
<p>Linked Wellness is currently carrying out a short update. We’ll check whether the site is back automatically; you can also refresh the page anytime.</p>
<div class="maintenance-progress-wrap" role="status" aria-live="polite" aria-atomic="true">
<div class="maintenance-progress-label">
<span>Checking again in</span>
<strong id="maintenance-countdown">—</strong>
</div>
<div class="maintenance-track" aria-hidden="true">
<div class="maintenance-bar" id="maintenance-bar"></div>
</div>
<p class="maintenance-eta" id="maintenance-eta-line">
<strong>Approximate time back:</strong>
<span id="maintenance-eta">—</span>
<span class="maintenance-eta-local"> (your local time)</span>
</p>
</div>
<p class="retry" id="maintenance-refresh-note">This page will reload automatically when the timer ends.</p>
</div>
<script>
(function () {
var total = 60;
var bar = document.getElementById('maintenance-bar');
var countdownEl = document.getElementById('maintenance-countdown');
var etaEl = document.getElementById('maintenance-eta');
var started = Date.now();
function pad(n) { return n < 10 ? '0' + n : String(n); }
function formatRemaining(sec) {
if (sec <= 0) return '0:00';
var m = Math.floor(sec / 60);
var s = sec % 60;
return m > 0 ? m + ':' + pad(s) : '0:' + pad(s);
}
function tick() {
var elapsed = Math.floor((Date.now() - started) / 1000);
var left = Math.max(0, total - elapsed);
var pct = total > 0 ? Math.min(100, (elapsed / total) * 100) : 100;
if (bar) bar.style.width = pct + '%';
if (countdownEl) countdownEl.textContent = formatRemaining(left);
if (etaEl) {
var eta = new Date(Date.now() + left * 1000);
etaEl.textContent = eta.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
}
if (left <= 0) {
window.location.reload();
return;
}
setTimeout(tick, 250);
}
tick();
})();
</script>
</body>
</html>
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
V1 - Content
Read-only content API. All endpoints require an API key, sent as an
X-API-Key header (preferred) or an api_key query parameter.
List content
requires authentication
Example request:
curl --request GET \
--get "https://api.linkedwellness.ie/api/content?website_env=all&route=%2F&type=page&key=welcome.title" \
--header "X-API-Key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://api.linkedwellness.ie/api/content"
);
const params = {
"website_env": "all",
"route": "/",
"type": "page",
"key": "welcome.title",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"X-API-Key": "{YOUR_API_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (503):
Show headers
retry-after: 60
cache-control: no-cache, private
access-control-allow-origin: *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="60">
<title>Under maintenance - Linked Wellness</title>
<style>
* { box-sizing: border-box; }
:root {
--primary: #165d65;
--accent: #00b08b;
--background-start: #effcf9;
--background-end: #d9f7f0;
--surface: #ffffff;
--text: #0f172a;
--muted: #475569;
--border: rgba(15, 23, 42, 0.08);
}
body {
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--text);
background:
radial-gradient(circle at top, rgba(255, 255, 255, 0.95), transparent 35%),
linear-gradient(135deg, var(--background-start), var(--background-end));
-webkit-font-smoothing: antialiased;
}
.card {
width: 100%;
max-width: 34rem;
border-radius: 1.5rem;
border: 1px solid var(--border);
background: var(--surface);
padding: 2rem;
text-align: center;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
}
.logo-wrap {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
}
.logo {
display: block;
max-width: min(100%, 16rem);
max-height: 4rem;
width: auto;
height: auto;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 9999px;
padding: 0.45rem 0.85rem;
background: color-mix(in srgb, var(--accent) 10%, white);
color: var(--primary);
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
}
h1 {
margin: 1.25rem 0 0.75rem;
color: var(--primary);
font-size: clamp(1.75rem, 4vw, 2.35rem);
line-height: 1.15;
}
p {
margin: 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.7;
}
.retry {
margin-top: 1.25rem;
color: var(--primary);
font-size: 0.9375rem;
font-weight: 600;
}
.maintenance-progress-wrap {
margin-top: 1.5rem;
text-align: left;
}
.maintenance-progress-label {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.75rem;
margin-bottom: 0.5rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-progress-label strong {
color: var(--primary);
font-weight: 700;
}
.maintenance-track {
height: 0.5rem;
border-radius: 9999px;
background: color-mix(in srgb, var(--primary) 10%, white);
overflow: hidden;
}
.maintenance-bar {
height: 100%;
width: 0%;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
transition: width 0.25s linear;
}
.maintenance-eta {
margin-top: 0.75rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-eta strong {
color: var(--text);
font-weight: 600;
}
.maintenance-eta-local {
color: var(--muted);
font-weight: 400;
}
.divider {
width: 4rem;
height: 0.25rem;
margin: 1.25rem auto 1.5rem;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
}
@media (max-width: 640px) {
.card {
padding: 1.5rem;
border-radius: 1.25rem;
}
.logo {
max-width: 12rem;
max-height: 3.25rem;
}
}
</style>
</head>
<body>
<div class="card">
<div class="logo-wrap">
<img class="logo" src="/images/Linked_Wellness_Logo_CMYK_Colour_Positive_Horizontal.svg" alt="Linked Wellness">
</div>
<div class="eyebrow">Scheduled maintenance</div>
<h1>We’ll be back shortly</h1>
<div class="divider"></div>
<p>Linked Wellness is currently carrying out a short update. We’ll check whether the site is back automatically; you can also refresh the page anytime.</p>
<div class="maintenance-progress-wrap" role="status" aria-live="polite" aria-atomic="true">
<div class="maintenance-progress-label">
<span>Checking again in</span>
<strong id="maintenance-countdown">—</strong>
</div>
<div class="maintenance-track" aria-hidden="true">
<div class="maintenance-bar" id="maintenance-bar"></div>
</div>
<p class="maintenance-eta" id="maintenance-eta-line">
<strong>Approximate time back:</strong>
<span id="maintenance-eta">—</span>
<span class="maintenance-eta-local"> (your local time)</span>
</p>
</div>
<p class="retry" id="maintenance-refresh-note">This page will reload automatically when the timer ends.</p>
</div>
<script>
(function () {
var total = 60;
var bar = document.getElementById('maintenance-bar');
var countdownEl = document.getElementById('maintenance-countdown');
var etaEl = document.getElementById('maintenance-eta');
var started = Date.now();
function pad(n) { return n < 10 ? '0' + n : String(n); }
function formatRemaining(sec) {
if (sec <= 0) return '0:00';
var m = Math.floor(sec / 60);
var s = sec % 60;
return m > 0 ? m + ':' + pad(s) : '0:' + pad(s);
}
function tick() {
var elapsed = Math.floor((Date.now() - started) / 1000);
var left = Math.max(0, total - elapsed);
var pct = total > 0 ? Math.min(100, (elapsed / total) * 100) : 100;
if (bar) bar.style.width = pct + '%';
if (countdownEl) countdownEl.textContent = formatRemaining(left);
if (etaEl) {
var eta = new Date(Date.now() + left * 1000);
etaEl.textContent = eta.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
}
if (left <= 0) {
window.location.reload();
return;
}
setTimeout(tick, 250);
}
tick();
})();
</script>
</body>
</html>
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get content by route
requires authentication
Example request:
curl --request GET \
--get "https://api.linkedwellness.ie/api/content/route//?website_env=all" \
--header "X-API-Key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://api.linkedwellness.ie/api/content/route//"
);
const params = {
"website_env": "all",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"X-API-Key": "{YOUR_API_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (503):
Show headers
retry-after: 60
cache-control: no-cache, private
access-control-allow-origin: *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="60">
<title>Under maintenance - Linked Wellness</title>
<style>
* { box-sizing: border-box; }
:root {
--primary: #165d65;
--accent: #00b08b;
--background-start: #effcf9;
--background-end: #d9f7f0;
--surface: #ffffff;
--text: #0f172a;
--muted: #475569;
--border: rgba(15, 23, 42, 0.08);
}
body {
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--text);
background:
radial-gradient(circle at top, rgba(255, 255, 255, 0.95), transparent 35%),
linear-gradient(135deg, var(--background-start), var(--background-end));
-webkit-font-smoothing: antialiased;
}
.card {
width: 100%;
max-width: 34rem;
border-radius: 1.5rem;
border: 1px solid var(--border);
background: var(--surface);
padding: 2rem;
text-align: center;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
}
.logo-wrap {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
}
.logo {
display: block;
max-width: min(100%, 16rem);
max-height: 4rem;
width: auto;
height: auto;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 9999px;
padding: 0.45rem 0.85rem;
background: color-mix(in srgb, var(--accent) 10%, white);
color: var(--primary);
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
}
h1 {
margin: 1.25rem 0 0.75rem;
color: var(--primary);
font-size: clamp(1.75rem, 4vw, 2.35rem);
line-height: 1.15;
}
p {
margin: 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.7;
}
.retry {
margin-top: 1.25rem;
color: var(--primary);
font-size: 0.9375rem;
font-weight: 600;
}
.maintenance-progress-wrap {
margin-top: 1.5rem;
text-align: left;
}
.maintenance-progress-label {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.75rem;
margin-bottom: 0.5rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-progress-label strong {
color: var(--primary);
font-weight: 700;
}
.maintenance-track {
height: 0.5rem;
border-radius: 9999px;
background: color-mix(in srgb, var(--primary) 10%, white);
overflow: hidden;
}
.maintenance-bar {
height: 100%;
width: 0%;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
transition: width 0.25s linear;
}
.maintenance-eta {
margin-top: 0.75rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-eta strong {
color: var(--text);
font-weight: 600;
}
.maintenance-eta-local {
color: var(--muted);
font-weight: 400;
}
.divider {
width: 4rem;
height: 0.25rem;
margin: 1.25rem auto 1.5rem;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
}
@media (max-width: 640px) {
.card {
padding: 1.5rem;
border-radius: 1.25rem;
}
.logo {
max-width: 12rem;
max-height: 3.25rem;
}
}
</style>
</head>
<body>
<div class="card">
<div class="logo-wrap">
<img class="logo" src="/images/Linked_Wellness_Logo_CMYK_Colour_Positive_Horizontal.svg" alt="Linked Wellness">
</div>
<div class="eyebrow">Scheduled maintenance</div>
<h1>We’ll be back shortly</h1>
<div class="divider"></div>
<p>Linked Wellness is currently carrying out a short update. We’ll check whether the site is back automatically; you can also refresh the page anytime.</p>
<div class="maintenance-progress-wrap" role="status" aria-live="polite" aria-atomic="true">
<div class="maintenance-progress-label">
<span>Checking again in</span>
<strong id="maintenance-countdown">—</strong>
</div>
<div class="maintenance-track" aria-hidden="true">
<div class="maintenance-bar" id="maintenance-bar"></div>
</div>
<p class="maintenance-eta" id="maintenance-eta-line">
<strong>Approximate time back:</strong>
<span id="maintenance-eta">—</span>
<span class="maintenance-eta-local"> (your local time)</span>
</p>
</div>
<p class="retry" id="maintenance-refresh-note">This page will reload automatically when the timer ends.</p>
</div>
<script>
(function () {
var total = 60;
var bar = document.getElementById('maintenance-bar');
var countdownEl = document.getElementById('maintenance-countdown');
var etaEl = document.getElementById('maintenance-eta');
var started = Date.now();
function pad(n) { return n < 10 ? '0' + n : String(n); }
function formatRemaining(sec) {
if (sec <= 0) return '0:00';
var m = Math.floor(sec / 60);
var s = sec % 60;
return m > 0 ? m + ':' + pad(s) : '0:' + pad(s);
}
function tick() {
var elapsed = Math.floor((Date.now() - started) / 1000);
var left = Math.max(0, total - elapsed);
var pct = total > 0 ? Math.min(100, (elapsed / total) * 100) : 100;
if (bar) bar.style.width = pct + '%';
if (countdownEl) countdownEl.textContent = formatRemaining(left);
if (etaEl) {
var eta = new Date(Date.now() + left * 1000);
etaEl.textContent = eta.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
}
if (left <= 0) {
window.location.reload();
return;
}
setTimeout(tick, 250);
}
tick();
})();
</script>
</body>
</html>
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get content by key
requires authentication
Example request:
curl --request GET \
--get "https://api.linkedwellness.ie/api/content/key/welcome.title?website_env=all" \
--header "X-API-Key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://api.linkedwellness.ie/api/content/key/welcome.title"
);
const params = {
"website_env": "all",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"X-API-Key": "{YOUR_API_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (503):
Show headers
retry-after: 60
cache-control: no-cache, private
access-control-allow-origin: *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="60">
<title>Under maintenance - Linked Wellness</title>
<style>
* { box-sizing: border-box; }
:root {
--primary: #165d65;
--accent: #00b08b;
--background-start: #effcf9;
--background-end: #d9f7f0;
--surface: #ffffff;
--text: #0f172a;
--muted: #475569;
--border: rgba(15, 23, 42, 0.08);
}
body {
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--text);
background:
radial-gradient(circle at top, rgba(255, 255, 255, 0.95), transparent 35%),
linear-gradient(135deg, var(--background-start), var(--background-end));
-webkit-font-smoothing: antialiased;
}
.card {
width: 100%;
max-width: 34rem;
border-radius: 1.5rem;
border: 1px solid var(--border);
background: var(--surface);
padding: 2rem;
text-align: center;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
}
.logo-wrap {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
}
.logo {
display: block;
max-width: min(100%, 16rem);
max-height: 4rem;
width: auto;
height: auto;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 9999px;
padding: 0.45rem 0.85rem;
background: color-mix(in srgb, var(--accent) 10%, white);
color: var(--primary);
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
}
h1 {
margin: 1.25rem 0 0.75rem;
color: var(--primary);
font-size: clamp(1.75rem, 4vw, 2.35rem);
line-height: 1.15;
}
p {
margin: 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.7;
}
.retry {
margin-top: 1.25rem;
color: var(--primary);
font-size: 0.9375rem;
font-weight: 600;
}
.maintenance-progress-wrap {
margin-top: 1.5rem;
text-align: left;
}
.maintenance-progress-label {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.75rem;
margin-bottom: 0.5rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-progress-label strong {
color: var(--primary);
font-weight: 700;
}
.maintenance-track {
height: 0.5rem;
border-radius: 9999px;
background: color-mix(in srgb, var(--primary) 10%, white);
overflow: hidden;
}
.maintenance-bar {
height: 100%;
width: 0%;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
transition: width 0.25s linear;
}
.maintenance-eta {
margin-top: 0.75rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-eta strong {
color: var(--text);
font-weight: 600;
}
.maintenance-eta-local {
color: var(--muted);
font-weight: 400;
}
.divider {
width: 4rem;
height: 0.25rem;
margin: 1.25rem auto 1.5rem;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
}
@media (max-width: 640px) {
.card {
padding: 1.5rem;
border-radius: 1.25rem;
}
.logo {
max-width: 12rem;
max-height: 3.25rem;
}
}
</style>
</head>
<body>
<div class="card">
<div class="logo-wrap">
<img class="logo" src="/images/Linked_Wellness_Logo_CMYK_Colour_Positive_Horizontal.svg" alt="Linked Wellness">
</div>
<div class="eyebrow">Scheduled maintenance</div>
<h1>We’ll be back shortly</h1>
<div class="divider"></div>
<p>Linked Wellness is currently carrying out a short update. We’ll check whether the site is back automatically; you can also refresh the page anytime.</p>
<div class="maintenance-progress-wrap" role="status" aria-live="polite" aria-atomic="true">
<div class="maintenance-progress-label">
<span>Checking again in</span>
<strong id="maintenance-countdown">—</strong>
</div>
<div class="maintenance-track" aria-hidden="true">
<div class="maintenance-bar" id="maintenance-bar"></div>
</div>
<p class="maintenance-eta" id="maintenance-eta-line">
<strong>Approximate time back:</strong>
<span id="maintenance-eta">—</span>
<span class="maintenance-eta-local"> (your local time)</span>
</p>
</div>
<p class="retry" id="maintenance-refresh-note">This page will reload automatically when the timer ends.</p>
</div>
<script>
(function () {
var total = 60;
var bar = document.getElementById('maintenance-bar');
var countdownEl = document.getElementById('maintenance-countdown');
var etaEl = document.getElementById('maintenance-eta');
var started = Date.now();
function pad(n) { return n < 10 ? '0' + n : String(n); }
function formatRemaining(sec) {
if (sec <= 0) return '0:00';
var m = Math.floor(sec / 60);
var s = sec % 60;
return m > 0 ? m + ':' + pad(s) : '0:' + pad(s);
}
function tick() {
var elapsed = Math.floor((Date.now() - started) / 1000);
var left = Math.max(0, total - elapsed);
var pct = total > 0 ? Math.min(100, (elapsed / total) * 100) : 100;
if (bar) bar.style.width = pct + '%';
if (countdownEl) countdownEl.textContent = formatRemaining(left);
if (etaEl) {
var eta = new Date(Date.now() + left * 1000);
etaEl.textContent = eta.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
}
if (left <= 0) {
window.location.reload();
return;
}
setTimeout(tick, 250);
}
tick();
})();
</script>
</body>
</html>
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get content for a website environment
requires authentication
Example request:
curl --request GET \
--get "https://api.linkedwellness.ie/api/content/environment/master" \
--header "X-API-Key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://api.linkedwellness.ie/api/content/environment/master"
);
const headers = {
"X-API-Key": "{YOUR_API_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (503):
Show headers
retry-after: 60
cache-control: no-cache, private
access-control-allow-origin: *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="60">
<title>Under maintenance - Linked Wellness</title>
<style>
* { box-sizing: border-box; }
:root {
--primary: #165d65;
--accent: #00b08b;
--background-start: #effcf9;
--background-end: #d9f7f0;
--surface: #ffffff;
--text: #0f172a;
--muted: #475569;
--border: rgba(15, 23, 42, 0.08);
}
body {
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--text);
background:
radial-gradient(circle at top, rgba(255, 255, 255, 0.95), transparent 35%),
linear-gradient(135deg, var(--background-start), var(--background-end));
-webkit-font-smoothing: antialiased;
}
.card {
width: 100%;
max-width: 34rem;
border-radius: 1.5rem;
border: 1px solid var(--border);
background: var(--surface);
padding: 2rem;
text-align: center;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
}
.logo-wrap {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
}
.logo {
display: block;
max-width: min(100%, 16rem);
max-height: 4rem;
width: auto;
height: auto;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 9999px;
padding: 0.45rem 0.85rem;
background: color-mix(in srgb, var(--accent) 10%, white);
color: var(--primary);
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
}
h1 {
margin: 1.25rem 0 0.75rem;
color: var(--primary);
font-size: clamp(1.75rem, 4vw, 2.35rem);
line-height: 1.15;
}
p {
margin: 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.7;
}
.retry {
margin-top: 1.25rem;
color: var(--primary);
font-size: 0.9375rem;
font-weight: 600;
}
.maintenance-progress-wrap {
margin-top: 1.5rem;
text-align: left;
}
.maintenance-progress-label {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.75rem;
margin-bottom: 0.5rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-progress-label strong {
color: var(--primary);
font-weight: 700;
}
.maintenance-track {
height: 0.5rem;
border-radius: 9999px;
background: color-mix(in srgb, var(--primary) 10%, white);
overflow: hidden;
}
.maintenance-bar {
height: 100%;
width: 0%;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
transition: width 0.25s linear;
}
.maintenance-eta {
margin-top: 0.75rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-eta strong {
color: var(--text);
font-weight: 600;
}
.maintenance-eta-local {
color: var(--muted);
font-weight: 400;
}
.divider {
width: 4rem;
height: 0.25rem;
margin: 1.25rem auto 1.5rem;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
}
@media (max-width: 640px) {
.card {
padding: 1.5rem;
border-radius: 1.25rem;
}
.logo {
max-width: 12rem;
max-height: 3.25rem;
}
}
</style>
</head>
<body>
<div class="card">
<div class="logo-wrap">
<img class="logo" src="/images/Linked_Wellness_Logo_CMYK_Colour_Positive_Horizontal.svg" alt="Linked Wellness">
</div>
<div class="eyebrow">Scheduled maintenance</div>
<h1>We’ll be back shortly</h1>
<div class="divider"></div>
<p>Linked Wellness is currently carrying out a short update. We’ll check whether the site is back automatically; you can also refresh the page anytime.</p>
<div class="maintenance-progress-wrap" role="status" aria-live="polite" aria-atomic="true">
<div class="maintenance-progress-label">
<span>Checking again in</span>
<strong id="maintenance-countdown">—</strong>
</div>
<div class="maintenance-track" aria-hidden="true">
<div class="maintenance-bar" id="maintenance-bar"></div>
</div>
<p class="maintenance-eta" id="maintenance-eta-line">
<strong>Approximate time back:</strong>
<span id="maintenance-eta">—</span>
<span class="maintenance-eta-local"> (your local time)</span>
</p>
</div>
<p class="retry" id="maintenance-refresh-note">This page will reload automatically when the timer ends.</p>
</div>
<script>
(function () {
var total = 60;
var bar = document.getElementById('maintenance-bar');
var countdownEl = document.getElementById('maintenance-countdown');
var etaEl = document.getElementById('maintenance-eta');
var started = Date.now();
function pad(n) { return n < 10 ? '0' + n : String(n); }
function formatRemaining(sec) {
if (sec <= 0) return '0:00';
var m = Math.floor(sec / 60);
var s = sec % 60;
return m > 0 ? m + ':' + pad(s) : '0:' + pad(s);
}
function tick() {
var elapsed = Math.floor((Date.now() - started) / 1000);
var left = Math.max(0, total - elapsed);
var pct = total > 0 ? Math.min(100, (elapsed / total) * 100) : 100;
if (bar) bar.style.width = pct + '%';
if (countdownEl) countdownEl.textContent = formatRemaining(left);
if (etaEl) {
var eta = new Date(Date.now() + left * 1000);
etaEl.textContent = eta.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
}
if (left <= 0) {
window.location.reload();
return;
}
setTimeout(tick, 250);
}
tick();
})();
</script>
</body>
</html>
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get content by ID
requires authentication
Example request:
curl --request GET \
--get "https://api.linkedwellness.ie/api/content/1" \
--header "X-API-Key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://api.linkedwellness.ie/api/content/1"
);
const headers = {
"X-API-Key": "{YOUR_API_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (503):
Show headers
retry-after: 60
cache-control: no-cache, private
access-control-allow-origin: *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="60">
<title>Under maintenance - Linked Wellness</title>
<style>
* { box-sizing: border-box; }
:root {
--primary: #165d65;
--accent: #00b08b;
--background-start: #effcf9;
--background-end: #d9f7f0;
--surface: #ffffff;
--text: #0f172a;
--muted: #475569;
--border: rgba(15, 23, 42, 0.08);
}
body {
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--text);
background:
radial-gradient(circle at top, rgba(255, 255, 255, 0.95), transparent 35%),
linear-gradient(135deg, var(--background-start), var(--background-end));
-webkit-font-smoothing: antialiased;
}
.card {
width: 100%;
max-width: 34rem;
border-radius: 1.5rem;
border: 1px solid var(--border);
background: var(--surface);
padding: 2rem;
text-align: center;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
}
.logo-wrap {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
}
.logo {
display: block;
max-width: min(100%, 16rem);
max-height: 4rem;
width: auto;
height: auto;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 9999px;
padding: 0.45rem 0.85rem;
background: color-mix(in srgb, var(--accent) 10%, white);
color: var(--primary);
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
}
h1 {
margin: 1.25rem 0 0.75rem;
color: var(--primary);
font-size: clamp(1.75rem, 4vw, 2.35rem);
line-height: 1.15;
}
p {
margin: 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.7;
}
.retry {
margin-top: 1.25rem;
color: var(--primary);
font-size: 0.9375rem;
font-weight: 600;
}
.maintenance-progress-wrap {
margin-top: 1.5rem;
text-align: left;
}
.maintenance-progress-label {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.75rem;
margin-bottom: 0.5rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-progress-label strong {
color: var(--primary);
font-weight: 700;
}
.maintenance-track {
height: 0.5rem;
border-radius: 9999px;
background: color-mix(in srgb, var(--primary) 10%, white);
overflow: hidden;
}
.maintenance-bar {
height: 100%;
width: 0%;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
transition: width 0.25s linear;
}
.maintenance-eta {
margin-top: 0.75rem;
font-size: 0.875rem;
color: var(--muted);
}
.maintenance-eta strong {
color: var(--text);
font-weight: 600;
}
.maintenance-eta-local {
color: var(--muted);
font-weight: 400;
}
.divider {
width: 4rem;
height: 0.25rem;
margin: 1.25rem auto 1.5rem;
border-radius: 9999px;
background: linear-gradient(90deg, var(--primary), var(--accent));
}
@media (max-width: 640px) {
.card {
padding: 1.5rem;
border-radius: 1.25rem;
}
.logo {
max-width: 12rem;
max-height: 3.25rem;
}
}
</style>
</head>
<body>
<div class="card">
<div class="logo-wrap">
<img class="logo" src="/images/Linked_Wellness_Logo_CMYK_Colour_Positive_Horizontal.svg" alt="Linked Wellness">
</div>
<div class="eyebrow">Scheduled maintenance</div>
<h1>We’ll be back shortly</h1>
<div class="divider"></div>
<p>Linked Wellness is currently carrying out a short update. We’ll check whether the site is back automatically; you can also refresh the page anytime.</p>
<div class="maintenance-progress-wrap" role="status" aria-live="polite" aria-atomic="true">
<div class="maintenance-progress-label">
<span>Checking again in</span>
<strong id="maintenance-countdown">—</strong>
</div>
<div class="maintenance-track" aria-hidden="true">
<div class="maintenance-bar" id="maintenance-bar"></div>
</div>
<p class="maintenance-eta" id="maintenance-eta-line">
<strong>Approximate time back:</strong>
<span id="maintenance-eta">—</span>
<span class="maintenance-eta-local"> (your local time)</span>
</p>
</div>
<p class="retry" id="maintenance-refresh-note">This page will reload automatically when the timer ends.</p>
</div>
<script>
(function () {
var total = 60;
var bar = document.getElementById('maintenance-bar');
var countdownEl = document.getElementById('maintenance-countdown');
var etaEl = document.getElementById('maintenance-eta');
var started = Date.now();
function pad(n) { return n < 10 ? '0' + n : String(n); }
function formatRemaining(sec) {
if (sec <= 0) return '0:00';
var m = Math.floor(sec / 60);
var s = sec % 60;
return m > 0 ? m + ':' + pad(s) : '0:' + pad(s);
}
function tick() {
var elapsed = Math.floor((Date.now() - started) / 1000);
var left = Math.max(0, total - elapsed);
var pct = total > 0 ? Math.min(100, (elapsed / total) * 100) : 100;
if (bar) bar.style.width = pct + '%';
if (countdownEl) countdownEl.textContent = formatRemaining(left);
if (etaEl) {
var eta = new Date(Date.now() + left * 1000);
etaEl.textContent = eta.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
}
if (left <= 0) {
window.location.reload();
return;
}
setTimeout(tick, 250);
}
tick();
})();
</script>
</body>
</html>
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
V1
Get static data
requires authentication
Example request:
curl --request GET \
--get "https://api.linkedwellness.ie/api/data" \
--header "X-API-Key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://api.linkedwellness.ie/api/data"
);
const headers = {
"X-API-Key": "{YOUR_API_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, success):
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.