Skip to content

GET /meta/capabilities

Self-description of the installation

Item types, capability profiles, field types, enum values, limits, supported locales, layout hints, automation triggers and actions, and event types. Clients configure themselves from this instead of hard-coding values.

Responses

Example bash
curl -X GET "$HUBTASK_URL/meta/capabilities"

GET /meta/health

Deep self-diagnosis of the installation

The state of every dependency, the active feature restrictions, the backlogs, and the configuration warnings. Deliberately answers 200 even when status is degraded - the HTTP status describes whether the endpoint is reachable, the status field describes the system. The internal /meta/health on the operations listener serves the same report and answers 503 when the status is down, because a status page reads a status code and holds no token; this route does not, for the reason above.

One route, two answers. A credential holding admin:tenants is the installation's operator and receives the whole report. Any other reader receives status, version and degraded_features and nothing else: which features are degraded is a statement about what the reader is about to try, while the dependency names, the backlogs, the migration state and the configuration warnings are the installation's internals and do not cross a tenant boundary. That reader needs the ops:read scope and the permission a workspace administrator holds (STRUCTURE, or READ_CONFIGURATION for an auditor).

The unauthenticated probes /healthz, /startupz and /readyz live outside /api/v1 and return only status codes.

Responses

Example bash
curl -X GET "$HUBTASK_URL/meta/health" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

GET /quotas

The workspace's quota standing

Every quota as it applies to this workspace: the resolved ceiling (0 means unlimited), what is currently used where a live count exists, and the approach ratio. Needs the permission that manages structure, or the auditor's read-only configuration permission - a quota is workspace configuration, and who is near a wall is exactly what an auditor reads.

Responses

  • 200 The quota standing
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X GET "$HUBTASK_URL/quotas" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

GET /tenant

The workspace the caller is in, and how it is set up

The workspace's own view of itself: the slug it is reached by, its display name, its standing, the locale and time zone every member without a preference of their own falls back to, and the settings it configures - today the one switch that demands a second factor of its administrators. Needs READ, or the auditor's read-only configuration permission: how a workspace is set up is configuration, and an auditor reads configuration without holding READ. This is not /admin/tenants. That listing is the installation operator's and crosses workspaces; this answers one workspace to the people inside it, and answers no other.

Responses

Example bash
curl -X GET "$HUBTASK_URL/tenant" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

PATCH /tenant

Change how the workspace is set up

Merge-patch, so an absent key changes nothing and the caller sends only what moves. Needs the permission that manages structure. Auditable, with the before and the after of every field that moved. require_admin_totp is the old name of sign_in_policy.mfa_required_for, and it is not stored as itself: true asks for ADMINS where the rule in force demands less, false for NONE, and either is that change to the rule - with the rule's step-up, its lock and its "no loosening" check. Sent as it already reads, it moves nothing and asks for nothing. Sent beside a mfa_required_for that says otherwise, it is refused against /require_admin_totp as workspace.admin_flag_contradicts_rule. The slug does not move here. It is the hostname in multi mode and the base of the OIDC redirect this installation registered, so renaming it is the operator's operation at /admin/tenants rather than the workspace's. A body naming it is refused as an unknown field rather than accepted and quietly ignored. sign_in_policy - and require_admin_totp, which is a change to it - is what demands a step-up: a workspace's sign-in rule is what decides whether a stolen tab can weaken the way in, and the name, the locale and the zone are not. A body without the header is 403 step_up_required. Settings this version does not model are left where they are. A workspace's settings document outlives any one release of this client, and a partial write that rewrote it whole would discard what a later one put there.

Headers

NameTypeRequiredDescription
If-Matchstring optionalThe ETag of the state last read (optimistic locking).
X-Hubtask-Step-Upstring optionalThe proof a privileged operation demanded: the token POST /auth/step-up answered, consumed by this one call.

Request body application/merge-patch+json — WorkspaceUpdate

NameTypeRequiredDescription
display_namestring
  • minLength: 1
  • maxLength: 200
optional
default_localestring optionalA BCP-47 tag.
default_time_zonestring optionalAn IANA zone.
default_week_startstring
  • maxLength: 8
optionalMONDAY, SATURDAY or SUNDAY: the day a member's week starts on when they chose none of their own; another day is a field error.
require_admin_totpboolean optionalThe old name of sign_in_policy.mfa_required_for: true asks for ADMINS where the rule demands less, false for NONE.
sign_in_policySignInPolicyChange optionalThe switches this workspace is tightening.
min_lengthinteger optional
min_lowercaseinteger optional
min_uppercaseinteger optional
min_digitsinteger optional
min_symbolsinteger optional
min_classesinteger
  • minimum: 0
  • maximum: 4
optional
max_repeatinteger optional0 is off.
common_passwordsboolean optional
context_wordsboolean optional
breach_checkboolean optional
max_age_daysinteger optional0 is off, which is the shipped value.
history_countinteger optional0 is off.
min_age_hoursinteger optional0 is off.
mfa_required_forstring
  • NONE
  • ADMINS
  • EVERYONE
optional
methodsarray of SignInMethod optional
session_max_daysinteger optional
session_idle_minutesinteger optional0 is off.
imprint_urlstring optional
privacy_urlstring optional
terms_urlstring optional
accessibility_urlstring optional
terms_versionstring optionalThe terms' version, at most 64 characters without control characters; empty clears it.
managed_accountsboolean optional
private_hubsboolean optional
rotation_fromstring
  • now
optionalThe literal now, and nothing else: it asks every person in this workspace for a new password at their next sign-in and ends every session opened before this moment.

Responses

Example bash
curl -X PATCH "$HUBTASK_URL/tenant" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H 'If-Match: "<the ETag you read>"' \  -H "Content-Type: application/merge-patch+json" \  -d '{  "display_name": "string",  "default_locale": "string",  "default_time_zone": "string",  "default_week_start": "string",  "require_admin_totp": true,  "sign_in_policy": {}}'

GET /private-hubs

The workspace's private hubs, without their names

Every private hub of the workspace, the trashed ones included: whose it is - the accounts holding OWNER on it - and how much it holds, with no name, description or content. Enough to run the workspace - its storage, a person leaving - and nothing to read. Needs the permission that manages members. Oldest first; a workspace has a handful, so the answer is not paged.

Responses

  • 200 The private hubs
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X GET "$HUBTASK_URL/private-hubs" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

GET /private-hubs/{hubId}/accesses

Who opened this private hub through the emergency access, and why

Every emergency access to the hub, newest first, with the person who opened it, when, until when and the reason they gave. Read by whoever reads the hub - its members, and the workspace's owner while their access runs; to everybody else the hub is not there, and this answers not found as it does.

Path parameters

NameTypeRequiredDescription
hubIdstring (uuid) required

Responses

  • 200 The accesses
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X GET "$HUBTASK_URL/private-hubs/{hubId}/accesses" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

POST /private-hubs/{hubId}/accesses

Open a private hub through the emergency access

The workspace's owner - only the owner, as a person - opens a private hub they hold nothing in, for one hour, with a reason. Every member of the hub is told at once, in the same step: by mail where they have an address, and in the app whatever their mail did; the opening is in the workspace's trail. The hour is not extended, and a second access is refused while one runs (containers.emergency_running, naming its end); once it has ended, a new one is a new act, told again. During the hour the hub answers its opener as a hub of the workspace would, through the opener's own requests only - never into a device's copy, a calendar feed or a job. Demands a fresh step-up in the X-Hubtask-Step-Up header. A shared hub is refused (containers.emergency_not_private), and so is a private hub the owner already holds a role in (containers.emergency_not_needed).

Path parameters

NameTypeRequiredDescription
hubIdstring (uuid) required

Headers

NameTypeRequiredDescription
X-Hubtask-Step-Upstring optionalThe proof a privileged operation demanded: the token POST /auth/step-up answered, consumed by this one call.

Request body application/json — PrivateHubAccessRequest

NameTypeRequiredDescription
reasonstring
  • minLength: 1
  • maxLength: 500
requiredWhy the hub is opened.

Responses

Example bash
curl -X POST "$HUBTASK_URL/private-hubs/{hubId}/accesses" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Content-Type: application/json" \  -d '{  "reason": "string"}'