OSPulse

Tenancy & access

Everything in OSPulse belongs to a tenant. Repositories, scans, policies, alerts, tokens, settings, audit records — none of them exist outside one. Understanding the tenant boundary is the fastest way to reason about who can see what, what a token can do, and what happens to your data at the end.

The tenant is the isolation boundary

A tenant is the organisation-level container and the unit of isolation. There is no cross-tenant read path: a query issued in one tenant cannot return another tenant's rows, and this is enforced at the data layer rather than left to individual endpoints to remember.

That single fact explains a lot of the API's shape:

  • Nothing takes a tenant identifier. You never pass one, because your credential already determines it. Tenant-level endpoints are addressed as /api/v1/tenants/current/... for exactly this reason.
  • Identifiers are only meaningful inside a tenant. A repository ID from one tenant returns 404 in another — not 403, because from that tenant's perspective the object genuinely does not exist.
  • Settings are tenant-wide by default. Scoring weights, retention, benchmark profile and feature flags apply to everything in the tenant, not per repository.

Within a tenant, repositories can be organised further — by workspace, team, business criticality and lifecycle status — and those attributes are what policies, alert rules and reporting scope against. They are organisational structure, not security boundaries. The security boundary is the tenant.

One tenant or several?

Use separate tenants when you need genuine data isolation — a subsidiary with its own compliance obligations, or a customer estate you manage on their behalf. Use workspaces and teams inside one tenant when you want structure but shared policy, shared scoring and a single view of risk. Splitting tenants to model an org chart costs you the aggregate picture that made the product useful.

Users and roles

Human access is per user, and each user's capability inside the tenant is determined by the role they hold. The model separates three things deliberately:

  • Authentication — proving who you are. Handled by password or by your identity provider through SSO.
  • Membership — belonging to a tenant. Granted by invitation or provisioned automatically through SCIM.
  • Authorisation — what you may do once inside. Determined by role.

Roles range from full administrative control over tenant configuration, through day-to-day operational roles that can trigger scans and triage findings, down to read-only roles intended for auditors and reporting consumers — people who legitimately need to see the risk picture and pull evidence out of it, but must not be able to change policy, grant exceptions or alter settings.

That read-only tier matters more than it first appears. Compliance reviewers, internal audit and customer-security teams all need access to the same evidence your engineers see. Giving them a role that cannot mutate anything is what lets you say yes without widening your blast radius.

Removing a user is explicit:

bash
curl -X DELETE https://api.ospulse.app/api/v1/users/{userId} \
  -H "Authorization: Bearer $OSPULSE_TOKEN"

The exact roles available to you are listed in the tenant's user administration screen and depend on your plan. Configure the identity side of this in SSO & SCIM.

API tokens act within a tenant

A token is not a separate identity class with its own permission universe. It is a credential that acts inside one tenant with a bounded scope. Create one with:

bash
curl -X POST https://api.ospulse.app/api/v1/api-tokens \
  -H "Authorization: Bearer $OSPULSE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "ci-policy-gate",
        "roleScopeJson": "{\"roles\":[\"read\"]}",
        "expiresAtUtc": "2027-01-31T00:00:00Z"
      }'

Three properties are required, and each is required for a reason:

namestringRequired

A human-readable label. This is what appears in the token list and in audit records, so it should identify the consumerci-policy-gate, warehouse-sync — not the person who happened to create it.

roleScopeJsonstringRequired

The role scope the token carries. A token should hold the narrowest scope that lets its consumer do its job: a CI gate needs to read dependencies and evaluate policy, not to delete repositories or reconfigure SSO.

expiresAtUtcdate-timeRequired

An expiry. Mandatory rather than optional, because an unbounded credential is a credential nobody will ever rotate. A token that expires forces a rotation event you can plan, instead of a leak you discover.

List tokens with GET /api/v1/api-tokens and revoke immediately with DELETE /api/v1/api-tokens/{apiTokenId}. The token value itself is shown once at creation and is not recoverable — see Authentication.

One token per consumer

Sharing a single token across CI, a reporting job and a local script means you cannot revoke one without breaking the others, and the audit log cannot tell you which of them made a call. Issue a token per consumer and the incident response writes itself.

SSO and SCIM

For any organisation past a handful of people, identity should not live in OSPulse.

SSO delegates authentication to your identity provider, so account lifecycle, MFA policy and session control stay where they already are. Read the current configuration:

bash
curl https://api.ospulse.app/api/v1/auth/sso \
  -H "Authorization: Bearer $OSPULSE_TOKEN"

Configure it with POST /api/v1/auth/sso/configure.

SCIM closes the gap SSO leaves. SSO controls whether someone can sign in; it does not by itself tell OSPulse that a leaver's account should cease to exist, or that someone moving teams should change role. SCIM provisioning makes your identity provider the source of truth for membership: users are created, updated and deactivated in OSPulse as a consequence of changes in the directory.

OSPulse exposes a standard SCIM 2.0 service at /scim/v2/, including ServiceProviderConfig, ResourceTypes and Schemas for discovery, full user lifecycle under /scim/v2/Users, and group listing at /scim/v2/Groups.

The deprovisioning gap is the one that bites

Joiners are self-correcting — someone complains within a day if access is missing. Leavers are silent. SCIM is worth configuring almost entirely for the offboarding half.

Tenant settings

Four categories of tenant-wide configuration change how OSPulse behaves for everything inside the boundary.

Scoring weights

Health scoring combines several components, and the weighting between them is a judgement about what your organisation actually cares about.

bash
curl https://api.ospulse.app/api/v1/tenants/current/scoring-weights \
  -H "Authorization: Bearer $OSPULSE_TOKEN"

Adjust with PATCH /api/v1/tenants/current/scoring-weights. Because weights are tenant-wide, changing them re-frames every score in the tenant at once — which is the point, but means it is not a change to make casually. Health snapshots record the weights in force when they were captured, so historical scores remain interpretable after a change.

Benchmark profile

GET and PATCH /api/v1/tenants/current/benchmark-profile describe your organisation — size band, sector and similar — so comparative analytics compare you against a meaningful peer set rather than the whole population. Benchmarking is opt-in (PUT /api/v1/analytics/benchmark/opt-in); an inaccurate profile produces a comparison that is precisely wrong.

Retention

GET and PATCH /api/v1/settings/retention govern how long historical data is kept — scan history, logs, audit records. Retention is a genuine trade-off rather than a "higher is better" setting: longer retention gives you deeper trend analysis and a fuller evidence trail, at the cost of holding more data than some data-protection positions want you to. Set it from your obligations, not from instinct.

Feature flags

GET /api/v1/feature-flags lists the capability flags in effect for the tenant, and PATCH /api/v1/feature-flags/{key} toggles those you control. Flags let a tenant adopt new behaviour on its own schedule rather than having it arrive with a deployment.

Usage and entitlements

Your plan defines entitlements — how many repositories, how much scanning, which capabilities. Current consumption against those limits is a single call:

bash
curl https://api.ospulse.app/api/v1/tenants/current/usage \
  -H "Authorization: Bearer $OSPULSE_TOKEN"

The response separates counters (what you have used) from quotas (what you are entitled to), which is what makes it useful to alert on. Watching the ratio lets you discover you are approaching a limit while there is still time to do something about it, rather than when an import starts failing.

Billing-side detail — the subscription itself, plan catalogue and invoices — lives under /api/v1/billing/. Plan limits vary; see pricing.

Getting your data out

Two mechanisms, for two different needs.

Full tenant export produces a complete archive of your tenant's data, asynchronously:

bash
curl -X POST https://api.ospulse.app/api/v1/tenants/current/data-export \
  -H "Authorization: Bearer $OSPULSE_TOKEN"

It returns 202 Accepted and processes in the background. This is the right tool for migration, for a data-subject or regulatory request, and for the "can we get our data back?" question that should be answered before you adopt any platform, not after.

Continuous export to your own analytics estate is a different problem, solved by warehouse export destinations under /api/v1/analytics/export/ — see Warehouse export. Use tenant export for a point-in-time copy and warehouse export for an ongoing feed.

SBOM generation (POST /api/v1/sbom/export) is narrower still: a standards-formatted inventory for a specific consumer. See SBOM generation.

Deleting a tenant

Tenant deletion is the one genuinely irreversible operation in the API.

bash
curl -X DELETE https://api.ospulse.app/api/v1/tenants/current \
  -H "Authorization: Bearer $OSPULSE_TOKEN"

This destroys the tenant and everything in it

Deletion removes repositories, scan history, findings, policies, exceptions, audit records and settings for the entire tenant. It is not a soft delete you can walk back, and support cannot restore a deleted tenant. Run a full data export first, confirm you have the archive, and confirm the credential you are using belongs to the tenant you intend to delete — the endpoint has no tenant identifier to check against, because it always acts on your own.

The endpoint requires appropriate administrative permission and may return 202 where deletion is processed asynchronously, or 204 where it completes immediately.

Audit logging

Every consequential action in a tenant is recorded: who did it, what changed, when, and from which actor type — a user, an API token, or the system itself.

bash
curl https://api.ospulse.app/api/v1/audit-log \
  -H "Authorization: Bearer $OSPULSE_TOKEN"

For evidence bundles and external review, GET /api/v1/audit-log/export produces the same records in an exportable form.

The audit log is what makes the rest of this page verifiable rather than merely stated. It is where you demonstrate that a policy exception was granted deliberately and by whom, that a departed engineer's token was revoked on the day they left, and that nobody quietly lowered a scoring weight before a compliance review. Treat it as the primary evidence surface it is: export it on a schedule, and give your auditors a read-only role rather than screenshots.

Next steps