Post an incident
const url = 'https://app.tunnelhq.com/api/v1/status-pages/sp_12/incidents';const options = { method: 'POST', headers: { 'X-Project-Id': 'prj_12', 'X-API-Key': '<X-API-Key>', 'Content-Type': 'application/json' }, body: '{"title":"Frankfurt tunnels are slow","impact":"degraded","status":"investigating","message":"We are looking into slow connections through Frankfurt.","service_ids":["sps_31"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://app.tunnelhq.com/api/v1/status-pages/sp_12/incidents \ --header 'Content-Type: application/json' \ --header 'X-API-Key: <X-API-Key>' \ --header 'X-Project-Id: prj_12' \ --data '{ "title": "Frankfurt tunnels are slow", "impact": "degraded", "status": "investigating", "message": "We are looking into slow connections through Frankfurt.", "service_ids": [ "sps_31" ] }'Posts an incident on the page, with its first update. It is public at once. message is plain text; web addresses
in it become links on the public page. It needs a role that can edit monitors (Owner, Admin and Manager have it by
default).
Need an API key? See Getting an API key.
Authorizations
Section titled “Authorizations”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”The project, as prj_12 or 12. A workspace key can only reach its own workspace’s projects.
Example
prj_12Request Bodyrequired
Section titled “Request Bodyrequired”object
How badly the incident affects the services. degraded_performance, partial_outage, major_outage and full_outage are also accepted on input.
Plain text. Web addresses in it become links.
The page’s services (sps_ IDs, from Get a status page) the incident affects.
Example
{ "title": "Frankfurt tunnels are slow", "impact": "degraded", "status": "investigating", "message": "We are looking into slow connections through Frankfurt.", "service_ids": [ "sps_31" ]}Responses
Section titled “ Responses ”The incident, public at once.
object
How badly the incident affects the services. degraded_performance, partial_outage, major_outage and full_outage are also accepted on input.
auto opened by itself when a service went down.
Someone has posted to it. An auto incident then no longer closes by itself.
Newest first.
object
Plain text.
Examples
A status page incident
{ "id": "spi_7", "title": "Frankfurt tunnels are slow", "impact": "degraded", "status": "investigating", "source": "manual", "edited": true, "started_at": "2026-11-07T08:12:00.000Z", "resolved_at": null, "service_ids": [ "sps_32" ], "updates": [ { "id": 1, "status": "investigating", "message": "We are looking into slow connections through Frankfurt.", "at": "2026-11-07T08:12:00.000Z" } ]}Headers
Section titled “Headers”Requests the workspace’s plan allows per minute.
Requests left in the current minute.
Unix time, in seconds, when the current minute ends.
The body is invalid: title, message or service_ids is missing, or impact or status isn’t allowed.
object
The HTTP status, repeated.
What went wrong.
More detail, on some errors.
Seconds to wait, on the 429 for wrong keys.
Examples
{ "error": true, "code": 400, "message": "impact must be one of degraded, partial, full, degraded_performance, partial_outage, major_outage, full_outage."}{ "error": true, "code": 400, "message": "Choose how bad it is: degraded, partial outage or full outage."}{ "error": true, "code": 400, "message": "Choose the services it affects on this page."}{ "error": true, "code": 400, "message": "Write the title."}{ "error": true, "code": 400, "message": "Write the update."}The API key is missing, wrong, expired, switched off, or no longer valid.
object
The HTTP status, repeated.
What went wrong.
More detail, on some errors.
Seconds to wait, on the 429 for wrong keys.
Examples
{ "error": true, "code": 401, "message": "API key is required. Provide X-API-Key header or Authorization: Bearer <key>"}{ "error": true, "code": 401, "message": "Invalid or expired API key"}{ "error": true, "code": 401, "message": "API key has expired"}{ "error": true, "code": 401, "message": "API key owner account is inactive"}{ "error": true, "code": 401, "message": "This API key's workspace access has been removed"}The role can’t edit monitors.
object
The HTTP status, repeated.
What went wrong.
More detail, on some errors.
Seconds to wait, on the 429 for wrong keys.
Example
{ "error": true, "code": 403, "message": "Posting status page incidents needs a role that can edit monitors in this project."}The project has no status page with this ID.
object
The HTTP status, repeated.
What went wrong.
More detail, on some errors.
Seconds to wait, on the 429 for wrong keys.
Example
{ "error": true, "code": 404, "message": "No such status page."}A usage limit was reached, or this IP address made too many requests with a wrong key.
Usage limits are per workspace and plan: per minute (Retry-After: 60), per day
(Retry-After: 3600), and per month (no Retry-After). They use their own body shape.
An IP address may send 10 wrong keys a minute; one more is allowed every 6 seconds. While
that allowance is used up, every request from the address is refused, even one with a
valid key.
object
Seconds to wait. Absent for the monthly limit.
object
The HTTP status, repeated.
What went wrong.
More detail, on some errors.
Seconds to wait, on the 429 for wrong keys.
Examples
{ "error": "Rate limit exceeded", "message": "Per-minute limit of 60 requests exceeded", "retry_after": 60}{ "error": "Daily limit exceeded", "message": "Daily limit of 25000 requests exceeded", "retry_after": 3600}{ "error": "Monthly limit exceeded", "message": "Monthly limit of 250000 requests exceeded"}{ "error": true, "code": 429, "message": "Too many failed API key attempts from this address. Wait a few seconds and try again.", "retry_after": 6}Headers
Section titled “Headers”Seconds to wait. 60 for the per-minute limit, 3600 for the daily limit, 6 after wrong keys. Absent for the monthly limit.
Something failed on TunnelHQ’s side.
object
The HTTP status, repeated.
What went wrong.
More detail, on some errors.
Seconds to wait, on the 429 for wrong keys.
Example
{ "error": true, "code": 500, "message": "Internal server error"}