Skip to main content

No matching sections.

Account, usage & quota

Four reads on account:read that answer the questions a client asks before it acts - what is this account allowed to do, how much of it has it already done, and how many API calls are left - and one write on account:write that changes the account's own details.

OperationAnswers
GET /accountEverything below in one document - identity, flags, package, usage, limits, badges.
GET /account/usageJust the consumption block.
GET /account/quotaAPI-call headroom, and the mintable scope catalogue.
GET /account/memberThe contacts holding shared access to this account.
PATCH /accountChange the account's own details - name, company, phone, country, time zone, language, default monitoring locations. Scope account:write.

GET /account

200 OK  ·  abridged
{
  "id": "3fa85f64-…",
  "login": "acme",
  "timezone": "Etc/UTC",
  "language": "it",
  "profile": {
    "firstName": "QA29437", "lastName": "", "company": "",
    "phone": "", "country": "", "email": "[email protected]"
  },
  "defaultAgentPools": { "legacy": ["allworld"] },
  "flags": { "enabled": true, "active": true, "overlimited": false, "apiEnabled": false },
  "package": { "id": "…", "name": "30-Days Free Trial", "features": { /* … */ } },
  "usage": { "monitor": { "used": 14, "allowed": 100 }, /* contact, report, maintenance */ },
  "overlimits": [],
  "limits": { "intervals": [60, 120, 180, /* 14 total */], "maxBulkItems": 5000, /* … */ },
  "badges": { "unconfirmedContacts": 0, "alerts24h": 0, "openIncidents": 0 }
}

This account is on the 30-Days Free Trial, whose package does not sell API access - hence flags.apiEnabled: false above; see flags below for why that is informational, not a gate. flags.disableReason and flags.stoppedAt are themselves omitted here rather than sent as null - both apply only to a disabled/stopped account, and this one is neither.

badges is the dashboard's attention row, readable programmatically: contacts still waiting for confirmation, alerts delivered in the last 24 hours, and currently-open incidents.

flags: the account's own state

flags is a bag of independent booleans, not a lifecycle: enabled, active and overlimited, plus disableReason and stoppedAt when they apply. Any combination can hold at once, which is precisely why it is not one word.

It was called state until 2026-08-17. On this surface state means one position in a lifecycle - a monitor's, a job's, an incident's - and a bag of independent booleans is not that. There is no alias: the old member is simply absent.
apiEnabled tells you whether this account may use the API at all. It is true when the package sells API access and the account's API policy is not negative - the same predicate the token mint runs. It never blocks a read: an account without it still gets its 200 and its (usually empty) quota document, which is exactly the state that used to be indistinguishable from a bug. What it cannot do is mint a token. ⚠ The mint also refuses while the account is suspended, and that is published separately as flags.active - so the honest client-side test for "can I mint a token" is apiEnabled && active. The two are kept apart on purpose: folded into one boolean, "why is my API off" stops being answerable.

overlimits beside it says which dimensions are over - task, contact, report, maintenance - and is empty when the account is inside its package. So flags.overlimited tells you that, and overlimits tells you what.

profile and default locations

profile is who the account is registered to, and defaultAgentPools is where a new monitor starts checking from. Both ride GET /account and both are written by PATCH /account - so a client reads the resource, edits it, and sends it back without ever leaving this endpoint.

MemberMeaning
profile.firstName / lastNameThe account holder's name. At most 50 characters each.
profile.companyThe organisation. At most 100 characters.
profile.phoneA contact number, stored as typed and never parsed as a number. At most 20 characters.
profile.countryAn ISO 3166-1 alpha-2 code - DE, US.
profile.emailThe login address. Read-only here - changing it is a confirmation-code flow on the sign-in surface, not a resource write.
timezone / languageOn the object root, not inside profile - where they have been since this endpoint shipped. Both are writable.
defaultAgentPoolsThe monitoring locations a new monitor of each service type starts with, keyed by service type and valued with pool ids, agent ids, or an agent id prefixed - to exclude it.
The five stored profile members read as "" when they are not set, never as null - they sit on columns that cannot hold null. That is also what makes "" the way to clear one. email is the exception and can be null.
defaultAgentPools is keyed by the service type's lowercase token - net, waterfall, internal, legacy, meta - the same spelling GET /agent/pool publishes its defaults under. It is the same map, and one fact gets one vocabulary. A PascalCase key (Net) is refused outright: 422 unknown_enum_value with reason: unknown_service_type and the accepted tokens listed in allowed.

PATCH /account

Changes the members the body names and leaves the rest alone. Answers 200 with the whole updated account - the same document GET /account returns - so nothing has to be re-read to confirm what was written. Scope account:write; a delegated member needs the profile-edit right. Idempotency-Key is accepted and not required.

A minimal patch, changing three members:

PATCH /account  ·  request
{
  "company": "Acme Ltd",
  "country": "GB",
  "timezone": "Europe/London"
}

Reads back with the whole account - the touched members updated, and timezone already in its IANA spelling:

PATCH /account  ·  200 OK, same shape as GET /account, abridged
{
  "id": "3fa85f64-…",
  "login": "acme",
  "timezone": "Europe/London",
  "profile": {
    "firstName": "QA29437", "lastName": "", "company": "Acme Ltd",
    "phone": "", "country": "GB", "email": "[email protected]"
  },
  /* language, defaultAgentPools, flags, package, usage, overlimits, limits, badges - unchanged, same shape as GET /account above */
}
MemberRules
firstName / lastName / company / phoneTrimmed; 50 / 50 / 100 / 20 characters. "" clears.
countryAn ISO 3166-1 alpha-2 code, matched against the platform's own country list. "" clears. An unknown code is 422 unknown_enum_value with reason: unknown_country.
timezoneA time-zone id - the IANA spelling (Europe/Berlin) or the Windows one; either is accepted and the IANA form is what reads back. There is no "no zone" state - send "UTC" rather than an empty value.
languageOne of the languages the platform actively translates; matched case-insensitively and stored in the roster's own spelling. Anything else is 422 unknown_enum_value with reason: unknown_language and the accepted list in allowed.
defaultAgentPoolsThe whole map, or null to clear every default. Each id is validated against the same location catalogue a monitor write uses.
defaultAgentPools REPLACES the map - it does not merge into it. Send the map you want the account to end up with: a body naming only waterfall leaves the account with a waterfall default and no others. null clears every default and a type mapped to [] clears that one. This is the same rule every nested object member on this surface follows, and merging would make "remove my net default" inexpressible.
Absent means unchanged; "" means clear; null on a text field is refused. Those columns cannot hold null, so null answers 422 validation_failed with reason: wrong_type and a detail pointing at the empty string. An empty body is a legal no-op: 200, nothing written.
An unrecognised location id is refused, not dropped. It answers 422 unknown_pool pointing at the exact element (/defaultAgentPools/net/1) with the selectable pools in valid. A save that silently discards half of what you sent and still answers 200 is the failure mode this surface refuses everywhere.
What this endpoint deliberately does not touch. The login email, the password and the API-token mint are confirmation-code and session flows, not resource writes - a long-lived token must not be able to change the credentials that would revoke it. Presentation preferences (date and time formats) are the web app's, not the account's. And nothing here moves money: this API publishes the entitlement half of billing and writes none of it.

package and features

package.features is the entitlement map: booleans and numeric caps, camelCase, and exactly the names a 403 package_limit problem puts in its feature field. That is the point of the shared spelling - a refusal names a key you can look up here, rather than prose you have to map by hand.

No price, no billing period, no balance. This endpoint answers "what may this account do", not "what is this account paying". Billing is not on the v2 surface.

usage: what you have spent

GET /account/usage - and the identical block on GET /account - reports consumption per domain under four singular keys, each {used, allowed}:

GET /account/usage  ·  200 OK
{
  "monitor":     { "used": 14, "allowed": 100 },
  "contact":     { "used": 3,  "allowed": 20 },
  "report":      { "used": 0,  "allowed": null },   // null = no limit
  "maintenance": { "used": 1,  "allowed": 0 }       // 0 = a real cap of none
}
allowed: null means "no limit". allowed: 0 means a real cap of none. They are different answers and a client must not collapse them. The keys were plural and the no-limit sentinel was -1 until 2026-08-17: any arithmetic on that sentinel - a progress bar, a "% used" figure, a pre-flight check - read an unlimited dimension as an already-breached cap. null cannot be arithmetic'd by accident.

limits: what a request may ask for

Where usage is about your rows, limits is about your requests - the numbers a client needs before it composes one:

MemberMeaning
intervalsThe check intervals this account may set. Read it instead of hardcoding - a value outside it is 422 invalid_interval, and that refusal echoes this same list in allowed.
alertDelaysThe alert delays a subscription may use, same deal.
maxBulkItems / maxBulkSelectionHow many items one bulk submission carries, and how large a filter-matched selection may be.
maxLimit / defaultLimitThe paging bounds - what ?limit= accepts, and what it is when omitted.
maxInlineContactsHow many contacts[] one POST /monitor may carry.
monitor / contactThe same bulk numbers again, per domain, where a domain differs from the account-wide figure.

quota: API call headroom

GET /account/quota reports how many API calls are left, without spending any of them. When at least one window is configured, its top-level limit/used/remaining/ resetAt describe the tightest-binding window - the one you will hit first. On an account with none configured - like the capture below - those members, each pool's own limit, and tokenCap are omitted rather than sent as null, the same omit-when-absent rule flags.disableReason/stoppedAt follow above. And pools breaks it down:

GET /account/quota  ·  200 OK
{
  "pools": {
    "check":   { "quotas": [] },   // instant checks
    "account": { "quotas": [] }    // everything else
  },
  "scopes": [ { "scope": "monitor:read", "description": "…" }, /* 20 rows */ ],
  "apiEnabled": false
}

Each entry of a pool's quotas[] is one configured window:

MemberMeaning
scopeWhich scope the window applies to.
quotaWhich quota this is - requests-per-minute, checks-per-month, and so on.
limit / used / remainingThe window's arithmetic.
resetAt / windowSecWhen used returns to zero, and how long the window is.
successOnlyTrue when only SUCCESSFUL requests count - a 4xx/5xx does not spend the quota. It changes how you should read remaining, so it is stated rather than assumed.
Empty quotas: [] is not a bug. It is what "no window is configured for this account" looks like on the wire - and on such an account ordinary calls carry no RateLimit-* headers either, and no 429 quota_exceeded. The anonymous reference tier is metered separately, per client address; see Authentication & scopes.

scopes[] is the mintable scope catalogue - all 20 (thirteen leaves plus seven families), each with a one-line description from the source registry. Build a token-scope picker from it rather than from a hardcoded list. tokenCap echoes the presented token's own self-cap when it carries one.

apiEnabled repeats GET /account's flags.apiEnabled here, because this is the document you read when you are asking "may I, and how much" - and those two halves should not cost two calls. false beside an empty pools means "the API is not enabled for this account", which is a different statement from "this account is not metered".

Shared access

GET /account/member lists the contacts holding shared access to this account - the subaccount graph, read-only here:

MemberMeaning
idThe membership row's id, which is the contact the access was granted to - the key the whole subaccount graph is stored under.
userIdThe delegate's own account id, once the invitation has been accepted. Null before that.
contactThe minimal identifying projection of the contact.
rightsThe granted rights as <area>:<read|write> tokens - monitor:write, contact:read, billing:read, profile:write, api:access, member:write, statusPage:read. Sorted, so two reads of the same grant are byte-equal.
stateactive | pending (invited, not yet confirmed) | disabled.
Member rights are not API token scopes, even where the words rhyme. A right governs what a delegated person may do in the account; a scope governs what a token may do. api:access is the right that lets a member use the API at all - and their calls are then bounded by their own token's scopes as well.