SWISS POST GROUP · SOVEREIGN BY DESIGN
AI Matrix
Platform
Solutions
Switch to OS
Resources
Partner
Company
Developers · Public API

Build on the platform. Automate what you operate.

A public REST API on api.open.ch, one versioned service at a time: fleet inventory, Mission Control ticketing, threat protection. Validation-first writes, full audit trail, machine-readable spec. Self-serve, no black boxes.

Base URL
https://api.open.ch
Auth
Authorization: Bearer <token>
Token lifetime
12 hours
Reference

Overview

The Open Systems Public API is a resource-oriented REST API. It accepts and returns JSON, authenticates with short-lived bearer tokens, and uses standard HTTP verbs and status codes. Each service ships its own independently versioned API under a common base URL, and the full endpoint reference is generated straight from the OpenAPI specification.

At a glance
Protocol
HTTPS only · JSON request & response bodies
Base URL
https://api.open.ch
Versioning
Per service: /api/<service>/v1/<resource> · each path versioned independently
Spec
OpenAPI 3.1 · Download the specification (JSON) · full reference in the API Knowledge Center (Mission Control)
Conventions
snake_case fields · IDs as strings · errors per RFC 9457
Getting started

Getting started

Four steps from zero to your first authenticated call. Everything is self-serve from Mission Control, the Open Systems Customer Portal.

Steps
01 · API user
Create an API User in the Mission Control API User management view and assign read and write access scopes. Save the client_id and client_secret. See API users →
02 · Token
Exchange the client credentials for an API token (valid 12 hours). See Authentication →
03 · Company ID
Most calls are scoped to your company_id. Find it in the Customer Portal URL (/companies/<company_id>) or ask your Technical Account Manager. See Fleet →
04 · First call
Call the API with the token in the Authorization header. See Conventions →
GET/api/fleet/v1/companies/{company_id}Your first authenticated request

Request

# after step 02 and 03 export API_TOKEN="<your_api_token>" export COMPANY_ID="<your_company_id>" curl -X GET "https://api.open.ch/api/fleet/v1/companies/$COMPANY_ID" \ --header "Authorization: Bearer ${API_TOKEN}"
Getting started

API users

API Users are dedicated machine identities, separate from the people who log in to the Customer Portal. Each one carries its own client credentials and a scoped set of permissions.

Managing API users
Create
In the Mission Control API Users view: add a user, configure access, generate client credentials. The client_secret is shown once - save it.
Read access
Enabled or disabled. Required for using any API.
Write scopes
Selected per API. Each write endpoint documents the scope it requires; a missing scope returns 403.
Rotate
Regenerate the secret to revoke and replace compromised credentials, or revoke without replacement.
Mission Control: Add API User form with username, secret generation, read access and write access scopes
Creating an API User in Mission Control: username, credentials, read access and write scopes in one form.
Mission Control shows the generated client ID and client secret once after saving
Credentials are displayed once - copy and store them safely.
Selecting write access scopes such as Threat Protection or Ticket for an API User
Write access is granted per scope, matching the write endpoints.
Endpoint reference showing the required API user access, e.g. write access on scope Threat Protection
Every endpoint in the reference states the access it requires; a missing scope returns 403.

Keep credentials out of public repositories and client-side code. If they leak, revoke or regenerate them immediately.

Getting started

Authentication

Every request is authenticated with a bearer token obtained via the OAuth 2.0 client-credentials flow. Tokens are validated by the Open Systems Identity Platform and expire after 12 hours; request a new one the same way.

POST/api/auth/v1/oauth/v2/tokenExchange client credentials for an API token

Request

# client-credentials grant export CLIENT_ID="<client_id>" export CLIENT_SECRET="<client_secret>" curl -X POST "https://api.open.ch/api/auth/v1/oauth/v2/token" \ --header 'Content-Type: application/x-www-form-urlencoded' \ --user "${CLIENT_ID}:${CLIENT_SECRET}" \ --data grant_type='client_credentials' \ --data scope='urn:open:api:public'

Response · 200

{ "access_token": "<api_token>", "token_type": "Bearer", "expires_in": 43200 }
Using the token
Header
Authorization: Bearer <api_token> on every request
Lifetime
12 hours · request a new token after expiry
Invalid token
Invalid, expired or missing tokens return 401 Unauthorized
Working with the API

Conventions

Consistent rules across every service: predictable pagination, snake_case fields, string IDs, and structured errors.

Rules
Pagination
Offset-based (?limit=100&offset=0, stable datasets) or cursor-based (?limit=100&cursor=…, large changing datasets), per endpoint
Sorting
order_by and order (ASC | DESC)
Fields
All field names in snake_case, in bodies and query parameters
IDs
All IDs are strings, e.g. "1234567"
Scoping
Most calls scoped by path, e.g. /companies/{company_id}/… · resource IDs via the Fleet API
GETPaginated listPagination metadata rides along with every list response

Offset-based

{ "data": [], "limit": 100, "offset": 0, "total": 520 }

Cursor-based

{ "data": [], "limit": 100, "next_cursor": "enz234t-3434…", "prev_cursor": "…" }
Working with the API

Reads & writes · CQRS

Writes follow the Command Query Responsibility Segregation pattern: every modification runs through an asynchronous change system that validates, audits and rolls out your configuration. You get a change ID to track, and a dry-run /validate twin for every write endpoint - so you can test a change before it touches anything.

How writes work
Validate first
Every write endpoint has a /validate counterpart: same request, full validation, zero side effects
Submit
POST · PUT · PATCH · DELETE return a change_id, not the modified data
Track
Poll the change status until COMPLETED or FAILED
Consistency
Reads may trail a completed write briefly - poll the status, then read
GET/api/self-service/v1/companies/{company_id}/changes/{change_id}/outputTrack a submitted change

Write response

{ "change_id": "123e4567-e89b-12d3-a456-426614174000" }

Status response

{ "status": "RUNNING" } # poll until COMPLETED or FAILED
Working with the API

Errors

Standard HTTP status codes, with a structured JSON body per RFC 9457 so you can handle failures programmatically. Every error carries a trace_id - include it when you contact support.

4xx · 5xxProblem detailsSame envelope for every failure

Example · 500

{ "title": "Internal Server Error", "status": 500, "detail": "failed to retrieve company tickets", "trace_id": "123e4567-e89b-…", "errors": [{ "message": "it was not possible to resolve the requested organization id…" }] }

Common codes

400 Bad request
401 Unauthorized
403 Forbidden
404 Not found
429 Rate limited
451 Inappropriate content
500 Server error
503 Unavailable
Working with the API

Rate limits

Limits protect availability for everyone and are applied per authentication token and per API path.

Behavior
Scope
Per token · per API path
Exceeded
429 Too Many Requests · responses may include usage and reset headers
Clients
Implement backoff logic to handle 429 gracefully
Working with the API

Versioning

Versions live in the URL and each path is versioned independently. Within a version, backwards compatibility is maintained; breaking changes ship as a new major version.

Policy
URL versioning
/api/ticketing/v1/… · independent per path
Breaking changes
Only in a new major version (v2, v3)
Early access
Endpoints flagged EA may change without notice - do not use in production
Deprecation
Announced 12 months ahead · deprecated endpoints return a Deprecation header with the end-of-life date (RFC 9745)
Fleet API · Live

Fleet

Your inventory as an API: companies, hosts and services, with the identifiers (company_id, host_id, service_id) that scope requests across every other API.

GET/api/fleet/v1/companies/{company_id}/hostsList the hosts in your fleet

Request

curl "https://api.open.ch/api/fleet/v1/companies/$COMPANY_ID/hosts" \ --header "Authorization: Bearer ${API_TOKEN}"
GET/api/fleet/v1/hosts/{host_id}Retrieve a single host
GET/api/fleet/v1/companies/{company_id}Retrieve your company

Excerpt - the complete endpoint list (including sites and services) is in the OpenAPI specification.

Ticketing API · Live

Ticketing

Drive Mission Control programmatically: create and update tickets, follow events, approve change requests and exchange attachments - the same workflows your operations teams already run, as an API.

GET/api/ticketing/v1/companies/{company_id}/ticketsList tickets
POST/api/ticketing/v1/companies/{company_id}/ticketsCreate a ticket
PATCH/api/ticketing/v1/companies/{company_id}/tickets/{ticket_id}Update a ticket, e.g. set customer_reference
GET…/tickets/{ticket_id}/eventsFollow the ticket timeline · POST to add an event
PATCH…/tickets/{ticket_id}/change-requests/{change_request_id}Approve or decline: APPROVED · DENIED · ON_HOLD
POST…/tickets/{ticket_id}/attachmentsUpload an attachment (binary, file form-data part) · returns 201

Excerpt - the complete endpoint list with all parameters and schemas is in the OpenAPI specification.

Threat Protection API · Live

Threat Protection

Manage block lists and exclusion lists as code: bulk create, modify and delete entries for IPs, domains and URLs across categories like MALWARE, PHISHING and SPAM. All writes are asynchronous CQRS changes with a /validate dry run.

GET/api/threat-protection/v1/companies/{company_id}/block-list-entriesList block-list entries
POST…/block-list-entriesCreate entries in bulk · POST …/block-list-entries/validate to dry-run

Request body

{ "scope": , "entries": [], "ticket_id": , # optional "customer_reference": , # optional "change_description": # optional } # full schema in the OpenAPI spec

Response

{ "change_id": "123e4567-e89b-12d3-…" } # track via the Self-Service change # status endpoint (CQRS)
PATCH…/block-list-entries/{entry_id}Modify an entry · /validate twin available
DELETE…/block-list-entriesBulk delete up to 1000 entries by ID · /validate twin available
GET…/exclusion-list-entriesExclusion lists: same create / modify / delete / validate surface

Excerpt - the complete endpoint list with all parameters and schemas is in the OpenAPI specification.

Security Investigations API · Live

Security Investigations

Work NDR security investigations programmatically: modify the status of hosts that triggered an investigation, with the same validate-first CQRS write flow as every other API. Requires write access on the Network Detection and Response scope.

PATCH/api/security-investigations/v1/companies/{company_id}/investigationsModify NDR investigations · /validate twin available

Excerpt - the complete endpoint list with all parameters and schemas is in the OpenAPI specification.

Firewall API · Live

Firewall

Read your managed firewall configuration programmatically: objects, policies with their forward and NAT rules, plus IANA reference lookups for IP protocols and ICMP types.

GET/api/firewall/v1/companies/{company_id}/objectsAll firewall objects of a company, including shared objects
GET/api/firewall/v1/companies/{company_id}/policiesList policies (metadata) · /policies/{policy_id} returns a policy with all rules
GET/api/firewall/v1/ip-protocolsIANA lookups: /ip-protocols · /icmp-types · /icmpv6-types

The complete endpoint list with all parameters and schemas is in the OpenAPI specification.

Logs API · Live

Logs

Retrieve platform and security logs programmatically and feed them into your own analytics or SIEM stack.

The Logs API is a different type of API and not part of the OpenAPI specification - it is documented in the Mission Control Help Section.

Self-Service API · Live

Self-Service

The change system behind every write. Track any submitted change to completion - the audit-friendly backbone of the CQRS pattern.

GET/api/self-service/v1/companies/{company_id}/changes/{change_id}/outputCurrent status of a change: RUNNINGCOMPLETED | FAILED

Excerpt - the complete endpoint list (including change search) is in the OpenAPI specification.

Roadmap

Roadmap

The API surface grows service by service - same base URL, same conventions, same validate-first write flow. What shipped recently, what we are building, and how you shape what comes next.

Recently shipped

Security Investigations API

Work NDR investigations programmatically.

Logs API

Platform and security logs for your own stack.

Threat Protection API

Bulk block and exclusion lists with /validate dry runs.

Change tracking

Follow every write to COMPLETED via the Self-Service API.

OpenAPI specification

Downloadable spec - generate typed clients in any language.

In development

Policy & ZTNA

Zero-trust access policy as code: declarative rules, validated before rollout, driven from your CI pipeline.

Web security

Programmatic control over secure web gateway and cloud-app rules across every user and location.

Shape what's next

Tell us what you need

Your integration needs an API we don't offer yet? Open a ticket in the Mission Control Portal - customer demand drives our sequence.

Early access program

New endpoints ship behind EA flags before general availability. Ask your Technical Account Manager to get in early. See Versioning →

Tooling

OpenAPI & clients

The endpoint reference is generated from our OpenAPI specification - every request and response body fully typed and documented. Use the spec to generate a client in your language of choice.

Specification
Reference
All endpoints, parameters and schemas, generated from the spec · API Knowledge Center in Mission Control
Clients
Generate client libraries from the spec with the OpenAPI generator of your choice
Download
open-systems-api-openapi.json · also available in the API Knowledge Center
Tooling

Tooling

First-class tooling is on its way. Until then, the OpenAPI specification is the recommended path to typed clients in any language.

Terraform Coming soon

Declarative infrastructure-as-code for your platform configuration.

registry.terraform.io
Reference

Migrating from the Legacy APIs

Integrations built on api.open-systems.com keep working until end of 2026, but new development belongs on api.open.ch. The essentials of the move:

What changes
Domain
api.open-systems.comapi.open.ch
Identity
Dedicated API Users with client credentials replace portal users with API keys
Fields & IDs
camelCasesnake_case · integer IDs → strings
Pagination
Page-based → offset-based: offset = (page - 1) * limit
Errors
Plain HTTP errors → structured problem details (RFC 9457)
Paths
/tickets → Ticketing API · /hosts → Fleet API · /utp → Threat Protection API
Writes
Synchronous responses → asynchronous CQRS changes with change_id tracking and /validate dry runs

The full migration guide with per-endpoint mappings and field renames lives in the API Knowledge Center in Mission Control.

Reference

Support

Run into an issue? Our Mission Control team has your back - the same Level-3 engineers who operate the platform.

Getting help
Channel
Open a ticket in the Mission Control Portal
Include
The trace_id from the error response · request timestamp · endpoint being accessed

Start building today.

Create an API user in Mission Control, grab a token, and make your first call in minutes.

Already a customerEverything you use today keeps running.