Skip to content

Guides

Conventions & versioning

The rules every endpoint follows, and what may change within v1.

Versioning and compatibility

The version is part of the path: /v1/…. Within v1, we make only additive changes:

  • New endpoints
  • New fields in responses
  • New error codes
  • New scopes

A new scope never changes what an existing key can do. Existing keys don’t receive it, so to call an endpoint that needs a new scope, create a key that has it. See Changing a key’s scopes.

Build your client to ignore fields it doesn’t recognize, and to handle unknown error codes by their HTTP status. Breaking changes, such as removing or renaming a field or changing its type or meaning, ship as a new version (/v2). We announce changes in the changelog.

Requests

  • All requests use HTTPS. v1 endpoints are read-only GET requests without a body.
  • Responses are JSON. Send Accept: application/json or omit the header. An Accept header that excludes JSON fails with 406 not_acceptable.
  • Other methods fail with 405 method_not_allowed, and unknown paths with 404 route_not_found. Paths are matched after percent-decoding.
  • Ids in paths and filters, such as policyId, are case-insensitive. Responses always use lowercase. The values of the platform and type filters are case-insensitive too, and the apps filter ignores the case of ASCII letters. The role and actor filters are exceptions. Send roles in lowercase, because any other case fails with 400 invalid_parameter. Send emails exactly as recorded, because actor is case-sensitive.
  • The time filters since and until are ISO-8601 timestamps with a UTC offset. since is inclusive and until is exclusive. See Time ranges.
  • On per-day lists, such as screen time and app usage, since and until are UTC calendar dates in the form YYYY-MM-DD, and both are inclusive. See Date ranges.

Strict query parameters

The API validates query parameters strictly, so a mistake returns an error instead of quietly returning unfiltered data. An unsupported parameter fails with 400 unknown_parameter. A parameter sent twice, or with an invalid value, fails with 400 invalid_parameter.

A typo in a parameter name
curl "https://api-gw.weguard.ai/core/v1/devices?platfrom=ios" \
  -H "Authorization: Bearer $WEGUARD_API_KEY"
400 Bad Request
{
  "type": "https://weguard.ai/docs/errors#unknown_parameter",
  "title": "Unknown parameter",
  "status": 400,
  "code": "unknown_parameter",
  "detail": "Unknown query parameter 'platfrom'. Allowed: platform, policyId, limit, cursor, includeTotal.",
  "instance": "/core/v1/devices",
  "requestId": "req_k3j2h1g0f9e8d7c6b5a4z3y2",
  "errors": [
    {
      "field": "platfrom",
      "code": "unknown_parameter",
      "message": "Unknown query parameter 'platfrom'. Allowed: platform, policyId, limit, cursor, includeTotal."
    }
  ]
}

Boolean parameters accept only true or false, in lowercase.

Response formats

  • JSON, UTF-8, with camelCase field names.
  • Timestamps are ISO-8601 in UTC, for example 2026-10-07T09:30:00Z. Calendar days, such as date on per-day resources, are UTC dates, for example 2026-10-07.
  • Ids are 24-character lowercase hexadecimal strings, for example 6523f1c2a7b9d40012345678. Treat them as opaque: store them as strings and don’t derive meaning from them.
  • Unknown values are null, not omitted. Every documented field is present in every response, unless its description says otherwise (for example, totalCount).
  • Errors use RFC 9457 problem details. See Errors.

The object field

Every resource has an object field naming its type, so you can tell payloads apart without knowing which endpoint they came from:

Platforms

Devices and policies have a platform. The platform filter takes the same values:

platformDevices
androidAndroid phones, tablets and dedicated devices
iosiPhone, iPad and iPod touch
macosMacs
tvosApple TV
windowsWindows PCs

Request ids

Every response has an X-Request-Id header, and every error body repeats it as requestId. You can send your own X-Request-Id to correlate our logs with yours. It must be 8 to 128 characters long and use only ASCII letters, digits and . _ : -. WeGuard echoes a valid value back. If you don’t send one, WeGuard generates one that starts with req_. A value that doesn’t match the format is replaced with a generated id.

bash
curl -i https://api-gw.weguard.ai/core/v1/me \
  -H "Authorization: Bearer $WEGUARD_API_KEY" \
  -H "X-Request-Id: cmdb-sync-2026-10-07-0001"

Conditional requests (ETags)

Successful GET responses include an ETag header. Send it back in If-None-Match. If the response would be identical, you get 304 Not Modified with an empty body and can reuse your cached copy. Responses carry Cache-Control: private, no-cache. Your client can store them but must revalidate them before reuse, and shared caches must not store them.

bash
curl -i https://api-gw.weguard.ai/core/v1/policies/64ff0a1b2c3d4e5f60718293 \
  -H "Authorization: Bearer $WEGUARD_API_KEY" \
  -H 'If-None-Match: "0d41d8cd98f00b204e9800998ecf8427e"'
Response
HTTP/1.1 304 Not Modified
ETag: "0d41d8cd98f00b204e9800998ecf8427e"
Cache-Control: private, no-cache
X-Request-Id: req_k3j2h1g0f9e8d7c6b5a4z3y2
RateLimit-Limit: 600
RateLimit-Remaining: 586
RateLimit-Reset: 2

A 304 saves bandwidth and parsing, but still counts toward your rate limit.

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