Docs
API overview
The API lets your own tools read what PulseKeeper knows: incidents, monitors and uptime. A typical use is a report you build yourself, for example a monthly summary in your own template or a dashboard that combines several services.
The API is read-only for now and is part of the Solo plan and above.
Endpoints
| Endpoint | |
|---|---|
GET /api/v1/incidents |
Confirmed incidents in a period, newest first |
GET /api/v1/incidents/{id} |
One incident |
GET /api/v1/monitors |
Every monitor of the team |
GET /api/v1/monitors/{id} |
One monitor |
GET /api/v1/monitors/{id}/uptime |
Availability of one monitor in a period |
All of them live under http://pulsekeeper.io/api/v1.
Tokens
Create a token under Settings → API. Only owners and admins can create or revoke one.
- A token belongs to the team, not to the person who created it. It keeps working when that person leaves.
- The token is shown once. We only store a hash of it, so copy it straight away. If you lose it, revoke it and create a new one.
- A team can have up to 10 tokens. Give each tool its own, so you can revoke one without breaking the others.
Authentication
Send the token in the Authorization header of every request, as Bearer followed by the token. Keep it on your server: anyone with the token can read your incidents.
cURL
curl http://pulsekeeper.io/api/v1/monitors \
-H "Authorization: Bearer $PULSEKEEPER_TOKEN" \
-H "Accept: application/json"
PHP
<?php
// composer require guzzlehttp/guzzle
$client = new GuzzleHttp\Client([
'base_uri' => 'http://pulsekeeper.io/api/v1/',
'headers' => [
'Authorization' => 'Bearer '.getenv('PULSEKEEPER_TOKEN'),
'Accept' => 'application/json',
],
]);
$monitors = json_decode($client->get('monitors')->getBody(), true)['data'];
JavaScript
const response = await fetch('http://pulsekeeper.io/api/v1/monitors', {
headers: {
Authorization: `Bearer ${process.env.PULSEKEEPER_TOKEN}`,
Accept: 'application/json',
},
});
const { data: monitors } = await response.json();
Go
req, _ := http.NewRequest("GET", "http://pulsekeeper.io/api/v1/monitors", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("PULSEKEEPER_TOKEN"))
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
Conventions
- IDs are short strings, such as
"3f9a1c0e7b2d4a58". Use them as they are; they never change. - Times are ISO 8601 in UTC, such as
"2026-09-30T21:14:05Z". Convert them to your own time zone for the report. - Periods take
fromandtoas a date or a date and time with an offset:2026-09-01or2026-09-01T00:00:00+02:00. In a URL, write the+as%2B. - Unknown is
null. A value we have not measured isnull, never0or100. - History goes back as far as your plan allows, the same as in the app. Asking for more returns
422with an explanation instead of a shorter answer, so a report never looks better than the month was.
Errors
Errors are JSON with a message; validation errors also have errors per parameter.
{
"message": "Your plan keeps 365 days of history.",
"errors": { "from": ["Your plan keeps 365 days of history."] }
}
| Status | Meaning |
|---|---|
401 |
The token is missing, wrong or revoked. |
403 |
Your plan no longer includes the API, or the account is suspended. The token itself stays and works again after the plan changes. |
404 |
No such incident or monitor in your team. |
422 |
A parameter is invalid or the period goes back further than your plan allows. |
429 |
Too many requests: wait for the number of seconds in the Retry-After header. |
Rate limit
120 requests per minute per token. Every answer carries X-RateLimit-Limit and X-RateLimit-Remaining. A monthly report for 50 clients fits easily; if you poll, once a minute is plenty, because incidents are confirmed within about a minute anyway.