Skip to article

HTTP API reference

This is a curated reference for the current public Bridge and its released clients. It covers authorized application data and public download metadata, not platform operations or the private device transport protocol.

Base origin: https://forge.readyit.dk. Routes below are relative to that origin.

Authentication, selection and JSON

Human application requests use a valid bearer access token for Forge and the X-Forge-Workspace-Id header selecting an authorized workspace UUID. Use the supported login flow; do not extract credentials from a profile or paste tokens into documentation, logs or customer messages.

GET /api/v1/tenants discovers the authenticated identity's memberships before selection. The header selects among existing memberships; it grants no authority. Human Admins and Technicians have ordinary workspace-wide access under the current workspace-humans-v2 policy. Settings, accounts, roles and invitations remain Admin-only.

Machines retain explicit test scope and are denied human directory, case, overview and generic history APIs. A human role claim does not turn a machine principal into a human.

Send request objects as application/json. Wire fields are snake_case; UUIDs are strings and timestamps use ISO 8601 with an offset. Nullable/optional response fields may be omitted. DTO names below identify documented wire contracts, not URLs or assembly-download instructions.

HTTP responses contain their actual object, array or page—not the CLI ok/data/next_actions envelope. Treat customer/history responses as private and honor Cache-Control: no-store. After a mutation times out, its completion may be unknown; do not assume it is safe to replay.

Public downloads

These GET routes require no login:

Route Result
/api/v1/client-configuration ClientConfigurationDto: public bridge_url, auth0_issuer, auth0_client_id, auth0_audience, expected_publisher. No user credentials or memberships.
/api/v1/cli/releases/latest?platform=win-x64 CliReleaseDto: schema_version, version, platform, expected_publisher, installer, archive. Each artifact contains url, size, sha256.
/api/v2/cli/releases/latest?platform=linux-x64 CliReleaseV2Dto: numeric schema_version, version, platform, signed package, target_payloads.
/api/v2/cli/releases/linux-x64/{version} Metadata for one verified Linux technician release.
/download/cli/win-x64/latest/installer Redirect to the selected Windows setup.
/download/cli/win-x64/latest/archive Redirect to the selected Windows ZIP.
/download/cli/linux-x64/latest/installer Redirect to the selected Linux setup.
/download/cli/linux-x64/latest/archive Redirect to the selected Linux archive.
/download/cli/linux-x64/latest/manifest Redirect to version-specific Linux release metadata.

PortableArtifactEnvelopeDto contains schema_version, algorithm, key_id, manifest and signature. The manifest/signature encode exact signed artifact identity, not a new trust key. Clients must verify with the approved independently pinned key, not trust arbitrary keys supplied beside a download. Use supported setup rather than implementing partial signature validation.

When downloading several artifacts, resolve a single release and use its immutable locations; independent latest requests can straddle a release change. Unavailable downloads fail explicitly.

Identity and enrolled devices

Method Route Response
GET /api/v1/tenants Array of TenantMembershipResponse.
GET /api/v1/me TechnicianIdentityResponse for the selected workspace.
GET /api/v1/devices Array of authorized DeviceSummaryResponse.
GET /api/v1/devices/{id} Authorized DeviceDetailsResponse.
PUT /api/v1/devices/{id}/metadata Updated device details; input UpdateDeviceMetadataRequest.

Key fields:

  • TenantMembershipResponse: tenant_id, name, role, current, optional legacy auth0_organization_id. Use the Forge workspace ID for selection.
  • TechnicianIdentityResponse: id, subject, display_name, optional email, tenant_id, tenant_name, role, device_access_mode.
  • Device summaries: id, machine_name, device_identifier, presence, last_seen_at, host_version, is_revoked, platform, optional descriptive labels and connection/transport metadata.
  • Device details add revocation, current lease/technician and SSH identity information. Compatibility fields do not imply a supported legacy transport; the released path is native relay.
  • UpdateDeviceMetadataRequest: nullable display_name, primary_user_name, organization_name. These do not update company/contact relationships.

Use forge device connect, exec, upload and download for remote work. The CLI owns key handling, exclusive leases, grant renewal and relay admission. There is no generic HTTP “execute a command” API in this reference.

Enrollment sharing

For authorized human device managers:

Method Route Request → response
POST /api/v1/enrollment-shares CreateEnrollmentShareRequestCreatedEnrollmentShareResponse.
GET /api/v1/enrollment-shares/{id} EnrollmentShareResponse.
DELETE /api/v1/enrollment-shares/{id} Updated EnrollmentShareResponse.

Creation input is label, platform (win-x64 or linux-x64) and optional expires_at. Null expiry means 24 hours; the maximum is seven days. The creation response has share and a one-time returned capability url. Never store that URL in an ordinary request log or operational receipt.

Status includes id, label/platform/release metadata, created_at, expires_at, state, and optional downloaded_at, consumed_at, online_at and enrolled_device_id. Status does not return a recoverable capability or code. Consumption and authenticated online presence are distinct.

Use enrollment guidance for delivery and installation; native code redemption and package trust belong to the signed client, not a browser script.

History and the work map

GET route Query and response
/api/v1/access-sessions Optional actor, device, state, since, until, cursor, limit; returns AccessSessionPage. State is active or ended.
/api/v1/access-sessions/{id} Optional cursor, limit; returns AccessSessionDetail.
/api/v1/access-activity/uncorrelated Optional device, cursor, limit; returns UncorrelatedActivityPage.
/api/v1/temporary-devices Optional history, cursor, limit; returns TemporaryDevicePage. history=true selects ended/promoted history.
/api/v1/temporary-devices/{id} TemporaryDeviceDetail, with separately authorized promotion information.
/api/v1/overview Optional customer, case, technician, activity, cursor; returns OverviewSnapshot. Activity is all, active or idle.

Session pages use items and next_cursor. Session detail instead has session, events, next_cursor. Session listing defaults to 25 items and detail to 50; both accept limits 1–100. since is inclusive and until exclusive on the access period's start.

AccessSessionSummary contains id, actor_id, actor_name, target_kind, target_id, target_name, started_at, last_observed_at, optional ended_at, state, end_reason, client_version, host_version. An AuditEventResponse includes event/actor/target identifiers, outcome, timestamps, optional version/transfer-hash metadata and provenance. These are metadata, not commands or file contents.

TemporaryDeviceDetail contains temporary, optional access_session_id, optional promotion, cleanup_outcome, optional cleanup_observed_at, and cleanup_provenance. A promotion's health_confirmed_at comes from the authenticated permanent device; a cleanup observation does not certify remote process removal. History access does not confer Rescue control.

OverviewSnapshot contains workspace_id, observed_at, policy_version, customer_context_available, enrolled/online counts, nodes, edges, groups, omitted_connections, next_cursor. Nodes identify company, case, technician, device, session or Rescue records. Groups include authorized total and expanded counts. The bounded map describes explicit relationships and observed access, not agent jobs or repair progress.

Customer directory

In the table, {collection} is companies or contacts.

Method Route Request → response
GET /api/v1/{collection} search, archive, cursor, limit; contacts also accept company. Returns CompanyPage or ContactPage.
GET /api/v1/{collection}/{id} CompanyDto or ContactDto, including archived records.
POST /api/v1/{collection} CompanyWriteRequest or ContactWriteRequest → created DTO, HTTP 201.
PUT /api/v1/{collection}/{id} Full write request with current version → updated DTO.
POST /api/v1/{collection}/{id}/archive DirectoryVersionRequest → updated DTO.
POST /api/v1/{collection}/{id}/restore DirectoryVersionRequest → updated DTO.
GET /api/v1/devices/{id}/customer-links DeviceCustomerLinksDto.
PUT /api/v1/devices/{id}/customer-links DeviceCustomerLinksRequest → updated links.

Write fields are display_name (1–200 characters), optional email (one address, up to 320), optional phone (up to 64), and version for updates. Contacts add nullable company_id. Omitted optional content fields clear them during an update. DirectoryVersionRequest is { "version": 1 }, with the actual current version substituted.

Company/contact DTOs include the content plus id, archived_at, version, created_at, updated_at. Contacts also return a display-only company reference. A reference has id, display_name, archived_at.

Device-link input must explicitly include both nullable company_id and primary_contact_id, plus its independent version. Null unlinks. The response includes device_id, the IDs, display-only company and primary_contact references, and the link version.

Pages have items, next_cursor; limit is 1–100, default 25. Archive is active (default), archived or all. Search is a literal case-insensitive name substring. Preserve the same filters when continuing a cursor.

See customers for full examples, preserved archived references and non-idempotent create/retry behavior.

Cases and narrative

All routes below start with /api/v1/cases. {id} is the case UUID.

Method Suffix Request → response
GET (none) Optional archive, one of device/session, cursor, limitCasePage<CaseDto>.
POST (none) CaseCreateRequestCaseDto, HTTP 201.
GET /members cursor, limitCasePage<CaseAuthorDto>; existing human collaborators, not account management.
GET / PUT /{id} Read CaseDto / replace with CaseWriteRequest.
POST /{id}/status CaseStatusRequestCaseDto.
POST /{id}/close, /reopen, /archive, /restore CaseVersionRequestCaseDto.
GET / POST /{id}/collaborators Array of CaseAssigneeDto / CaseAssigneeRequestCaseDto.
DELETE /{id}/collaborators/{member} Body CaseVersionRequestCaseDto.
GET / POST /{id}/links Array of CaseLinkDto / CaseLinkRequestCaseDto.
DELETE /{id}/links/{link} Body CaseVersionRequestCaseDto.
GET / POST /{id}/notes Paged CaseNoteDto / CaseNoteCreateRequestCaseNoteDto, HTTP 201.
GET / PUT /{id}/notes/{note} CaseNoteDto / CaseNoteWriteRequest → updated note.
GET /{id}/notes/{note}/revisions Paged CaseNoteRevisionDto.
GET / POST /{id}/drafts Paged CaseDraftDto / CaseDraftCreateRequestCaseDraftDto, HTTP 201.
GET / PUT /{id}/drafts/{draft} CaseDraftDto / CaseDraftWriteRequest → updated draft.

Every lifecycle suffix above is relative to /{id}; for example, reopening uses /api/v1/cases/{id}/reopen. Paged requests accept cursor and limit (1–50, default 25), returning items and next_cursor. Requests are limited to 128 KiB and reject unknown author/review claims.

Request shapes

DTO Fields
CaseCreateRequest Required title; optional description, company_id, primary_contact_id, device_id, access_session_id.
CaseWriteRequest Required version, title; replacement description, company_id, primary_contact_id.
CaseVersionRequest Current version.
CaseStatusRequest Current version, status: open, in_progress or waiting.
CaseAssigneeRequest Current case version, user_id.
CaseLinkRequest Current case version, kind: device or session, and target_id.
CaseNoteCreateRequest Required idempotency_key, body; kind defaults to finding, basis to observation; optional source, agent_name, references.
CaseNoteWriteRequest Current note version, replacement note fields; no idempotency key.
CaseDraftCreateRequest recipient_address, subject, body; optional recipient_contact_id.
CaseDraftWriteRequest Current draft version plus replacement draft fields. Every update clears review.

Case titles allow 200 characters and descriptions 8,000. Note/draft bodies allow 16,000; draft subjects 300 and recipient addresses 320. Notes accept kinds finding, action, result, next_step and bases observation, inference. Each of at most ten references has kind (device, session, authorized audit) and target_id.

Response and review contracts

  • CaseDto includes metadata, customer references, creator, timestamps, status, closed_at, archived_at, version.
  • CaseAuthorDto contains id, display_name, former_member.
  • CaseLinkDto contains its own unlinkable id, evidence, created_at. Unavailable evidence does not expose a target ID or label.
  • CaseNoteDto contains id, creator, created_at, current. current is an immutable attributed revision containing version, content, basis/source/agent labels, author, recorded_at, references.
  • CaseDraftDto contains recipient/contact, subject/body, its own version, author/timestamps, state, reviewed_version, reviewer, reviewed_at. It is a draft, never a delivery receipt.

There is no V1 draft review, reviewed-export or send API. Website review uses an explicit cookie-authenticated, antiforgery-protected action bound to the exact revision. Reviewed copy/download also reauthorizes that revision. API clients cannot assert review. See the case workflow.

Errors and retries

Common status meanings:

HTTP status Action
400 Correct malformed input, unsupported selection or invalid relationship.
401 / 403 Reauthenticate or verify current membership/feature authority; do not retry under an unrelated identity.
404 The record is unavailable under current scope; it may be missing or inaccessible.
409 Reload the current version or resolve lifecycle/idempotency conflict.
413 Reduce the bounded request body.
429 Respect throttling; slow down rather than repeating immediately.
503 Service or verified release unavailable; inspect state before retrying a write.

Many application failures return { "error": "<code>", "message": "<detail>" }. Overview has a separate code error field; authorization/routing failures may not return an application JSON body. Do not assume one universal error envelope.

Important feature codes include directory_not_found, directory_conflict, invalid_case, case_conflict, case_archived and case_storage_unavailable. An identical note-creation retry with the same actor, workspace, key and payload is idempotent. Other creates do not inherit that guarantee.