Skip to content

Guides

Errors

Failed requests return an HTTP status code and a JSON problem-details body with a stable error code you can branch on.

Error format

Errors follow RFC 9457 (Problem Details for HTTP APIs) and are served as application/problem+json:

400 Bad Request
{
  "type": "https://weguard.ai/docs/errors#invalid_parameter",
  "title": "Invalid parameter",
  "status": 400,
  "code": "invalid_parameter",
  "detail": "'limit' must be an integer between 1 and 100.",
  "instance": "/core/v1/devices",
  "requestId": "req_k3j2h1g0f9e8d7c6b5a4z3y2",
  "errors": [
    {
      "field": "limit",
      "code": "invalid_parameter",
      "message": "'limit' must be an integer between 1 and 100."
    }
  ]
}
type
string
URI that identifies the problem: https://weguard.ai/docs/errors#<code>. It links to the entry for the code on this page.
title
string
Short, human-readable summary of the problem type. Same for every occurrence of a code.
status
integer
The HTTP status code, repeated for convenience.
code
string
Stable, machine-readable error code. Branch on this value. Codes are never renamed, but new codes can be added.
detail
string
Human-readable explanation of this occurrence. The wording can change, so don’t parse it.
instance
string
The request path that failed.
requestId
string
Id of the request, also in the X-Request-Id header. Quote it when you contact support.
errors
array of objects
Per-parameter problems. Present only when specific parameters are at fault.
errors.field
string
The parameter at fault, such as limit.
errors.code
string
Error code for this parameter.
errors.message
string
Human-readable explanation.

Members without a value are omitted, not sent as null or an empty array. For example, errors appears only when specific parameters are at fault. Error responses are sent with Cache-Control: no-store.

HTTP status codes

StatusMeaning
200OKThe request succeeded.
304Not ModifiedThe resource has not changed since the ETag you sent in If-None-Match. The body is empty.
400Bad RequestA parameter is invalid, unknown or repeated, or the cursor is invalid.
401UnauthorizedThe API key is missing, malformed, unknown, expired or revoked, or the Authorization header does not use the Bearer scheme.
403ForbiddenThe key lacks a required scope, or its account is inactive.
404Not FoundThe route, or the resource in your account, does not exist.
405Method Not AllowedThe route does not support this method. See the Allow header.
406Not AcceptableThe Accept header excludes JSON.
422Unprocessable ContentThe request is valid, but the device’s platform does not report this resource.
429Too Many RequestsThe rate limit was exceeded. Honor Retry-After.
500Internal Server ErrorSomething went wrong on our side. Retry with backoff.
503Service UnavailableA dependency is temporarily unavailable. Honor Retry-After, then retry with backoff.

Error codes

This list covers every code the API returns. Each entry is the target of the type URI in the problem body, so https://weguard.ai/docs/errors#rate_limit_exceeded links straight to it.

Invalid parameter

A query parameter has an invalid value or was sent more than once. Examples: limit=0, includeTotal=yes, an unknown platform, an actor that is not an email address, a since / until that is not an ISO-8601 timestamp with an offset, a date that is not YYYY-MM-DD on a per-day list, an until date later than today, or a window longer than the endpoint allows.

What to do: Fix the parameter named in errors[].field and send the request again.

Unknown parameter

The request includes a query parameter the endpoint does not support. Parameters are matched strictly, so a typo such as ?platfrom=ios fails instead of silently returning unfiltered data.

What to do: Remove or correct the parameter. The detail lists the parameters the endpoint accepts. Endpoints that take no parameters reject every query parameter.

Invalid pagination cursor

The cursor is malformed, or it was issued for a request with different filters.

What to do: Pass nextCursor back exactly as you received it, with the same filters as the request that returned it, or start again without a cursor. See Pagination.

Missing credentials

The request has no Authorization header.

What to do: Send your API key as Authorization: Bearer wgk_…. See Authentication.

Invalid Authorization header

The Authorization header does not use the Bearer scheme, or has no key after it. The WWW-Authenticate header carries error="invalid_request".

What to do: Use Authorization: Bearer <key>. Basic auth, a custom header or the bare key will not work.

Invalid API key

The key is malformed, does not exist, or its secret does not match. The WWW-Authenticate header carries error="invalid_token".

What to do: Check that you copied the full key (wgk_<keyId>_<secret>) with no extra whitespace and nothing cut off. If you lost the secret, create a new key.

API key expired

The key is past its expiresAt.

What to do: Create a new key, deploy it, and remove the expired one from your configuration.

API key revoked

An account admin revoked the key. Revocation takes effect immediately and cannot be undone.

What to do: Ask an account admin for a new key.

Insufficient scope

The key is valid but lacks a scope the endpoint requires. The WWW-Authenticate header names the missing scopes.

What to do: Create a key with the required scopes. You cannot add scopes to an existing key. See Authorization.

Account inactive

The WeGuard account that owns the key has been deleted or disabled.

What to do: Contact your WeGuard account manager or support.

Resource not found

No resource with that id exists in your account. Resources that belong to other accounts, and values that are not well-formed ids, are reported the same way.

What to do: Check the id. Ids are 24-character hex strings returned by list endpoints.

Route not found

No endpoint matches the request path.

What to do: Check the URL against the API reference, including the /v1 prefix.

Location unavailable

The device exists but has not reported a location.

What to do: Treat the location as unknown. Location reporting depends on the device platform, policy and permissions.

Method not allowed

The route exists but does not support this HTTP method. The Allow header lists the methods it does support.

What to do: Use one of the methods in the Allow header. Every v1 endpoint is GET.

Not acceptable

The Accept header excludes JSON.

What to do: Send Accept: application/json or omit the header.

Unsupported platform

The device exists, but its platform does not report the data this endpoint returns. Screen time and app usage are available for Windows devices only. The detail names the device’s platform.

What to do: Don’t retry. Call the endpoint only for devices whose platform it supports, and skip the others. An empty list would wrongly suggest the device was not used, so the API returns this error instead.

Rate limit exceededRetryable

The key has used up its request budget. See Rate limits.

What to do: Wait for the number of seconds in Retry-After, then retry with exponential backoff and jitter.

Internal server errorRetryable

An unexpected error occurred on our side.

What to do: Retry with exponential backoff. If it persists, contact support and quote the requestId.

Service unavailableRetryable

A service WeGuard depends on is temporarily unavailable, or reading the data took longer than the time WeGuard allows for it. This can also happen while your key is being checked, so it can be returned before authentication completes. The response carries Retry-After.

What to do: Wait for the number of seconds in Retry-After, then retry with exponential backoff.

Console-only codes

Only API key management in the WeGuard console returns these codes. The /v1 API never does. They’re listed here so their type links resolve.

Malformed request bodyConsole only

The request body is missing or is not valid JSON.

What to do: Send a valid JSON body with Content-Type: application/json.

Validation failedConsole only

One or more body fields are invalid. Each problem is listed in errors[].

What to do: Correct the fields listed in errors[].

Invalid or expired sessionConsole only

The web console session is missing, invalid or expired.

What to do: Sign in to the WeGuard console again.

Insufficient roleConsole only

The console user is not an account admin, so they cannot manage API keys.

What to do: Ask an account admin to create or revoke the key.

API key limit reachedConsole only

The account already has the maximum number of active API keys.

What to do: Revoke a key that is no longer used, then create the new one.

Unsupported media typeConsole only

The request body is not JSON.

What to do: Send the body as application/json.

Retrying requests

Decide what to do from the status code, then the error code:

  • Retry 429, 500 and 503. If Retry-After is present, wait that many seconds. Otherwise, use exponential backoff with jitter, and cap the number of attempts.
  • Don’t retry other 4xx errors unchanged, because the same request will fail again. Fix the request, the key or its scopes first.
  • A 404 resource_not_found on a single resource usually means it was deleted or never existed in this account. Treat it as gone. 404 location_unavailable is different: the device exists but hasn’t reported a location yet. Keep the device and check again later.
  • A 422 unsupported_platform means the endpoint doesn’t serve the device’s platform. Don’t retry it. Skip such devices, for example by checking platform on the device first.
const RETRYABLE = new Set([429, 500, 503]);

async function weguardFetch(url, { maxAttempts = 5 } = {}) {
  for (let attempt = 1; ; attempt++) {
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.WEGUARD_API_KEY}` },
    });
    if (response.ok) return response.json();

    const problem = await response.json();
    if (!RETRYABLE.has(response.status) || attempt === maxAttempts) {
      throw new Error(`${problem.code}: ${problem.detail} (requestId ${problem.requestId})`);
    }

    // Honor Retry-After when present, else exponential backoff with full jitter.
    const retryAfter = Number(response.headers.get("Retry-After"));
    const backoff = Math.min(30_000, 500 * 2 ** attempt);
    const delay = retryAfter > 0 ? retryAfter * 1000 : Math.random() * backoff;
    await new Promise((resolve) => setTimeout(resolve, delay));
  }
}

All v1 endpoints are read-only GET requests, so retrying them never changes data.

Contacting support

Every response, successful or not, has an X-Request-Id header, and every error body repeats it as requestId. Log it with your errors and include it when you contact WeGuard support.

Bring your own request id

Send your own X-Request-Id (8 to 128 characters: ASCII letters, digits and . _ : -) to match WeGuard requests to your logs. See Request ids.

We use cookies

We use cookies to ensure you get the best experience on our website. For more information on how we use cookies, please see our cookie policy.

By clicking "Accept", you agree to our use of cookies.

Learn more