Session and Exposition contracts
The Exposition and CVE/KEV contracts on this page target staging. Download the separate OpenAPI JSON or YAML. This is a selected browser-session reference, not a complete workspace API or a promise of production availability. It is distinct from the personal API and organization service API.
Authentication and permissions
Browser requests use the __Host-ps session cookie. Unsafe methods also require the __Host-pc CSRF cookie and matching X-CSRF-Token header. Personal API keys and organization service credentials are not substitutes. An organization-scoped session remains restricted to that organization.
Exposition reads require access to an Exposition organization and the selected scope. External/client members and general-research spaces cannot use these endpoints. Writes require a writable organization; creation, lifecycle, timezone, monitoring and notification settings also require an owner or administrator. A member's assigned scope still limits decisions, history and reports. Authentication does not bypass those checks.
HTTP 401 means missing/invalid authentication; 403 a permission or CSRF refusal; 402 an entitlement or budget refusal; 409 a version/capacity conflict; 422 invalid input; 429 a rate/cadence limit. Read the actual error code, and refetch/reconcile after a version conflict.
Personal credit state
GET /api/v2/auth/credits returns monthly_credits, credits_used, purchased balance, lifetime_purchased, cycle_start, cycle_end, has_paid_entitlement, plan_label and is_legacy. These are session endpoints with no search charge. has_paid_entitlement is not a substitute for the live API-data access check: a Free account with a depleted purchased balance cannot spend its monthly allocation through /common/data.
GET /api/v2/auth/credits/usage returns the current cycle_start, usage and usage_mcp arrays of {category, credits}. The MCP array is a subset of the total, not an additional charge. Categories are host, dns, whois, certs, alerting, subdomains, exports and tools. Eligible session JSON object responses may also contain profundis_credits; streams and array responses do not use that injected object. See Credits.
Scope lifecycle
Paths below are relative to /api/v2/organizations/{orgId}. A scope is represented by a client resource in these routes.
| Method and path | Contract |
|---|---|
POST /exposure/scopes | name, domain, IANA timezone, optional addresses (up to 16 IPs), monitoring, credit_limit; returns a client view with 201 |
PATCH /clients/{clientId} | name and state (active or archived), with current quoted If-Match version |
DELETE /clients/{clientId} | Exact name in confirmation, with If-Match; 204 on success |
GET /clients/deleted | Up to 100 recoverable metadata entries for managers |
POST /clients/{clientId}/restore | Current If-Match; only before erase_after and before erasure begins |
Capacity billing ignores credit_limit; legacy credit billing requires 6–1,000,000. Creating a capacity-based scope starts an initial refresh from stored observations. Scheduled monitoring remains a separate setting. Declaring an asset does not authorize an active vulnerability scan.
Archiving stops queued/running work and monitoring, cancels deliveries and revokes guest report links. Deletion immediately removes access and starts a seven-day cancellation window; audit/accounting records remain. Restoration returns the scope to archived state. Grants, links and scheduled spending are not silently restored.
Inventory, decisions and history
Paths below use /api/v2/organizations/{orgId}/clients/{clientId}/exposure as their prefix. The inventory GET uses the prefix itself, without another segment.
| Method and suffix | Contract |
|---|---|
GET (prefix itself) | Inventory and observations; fixed pages of 100, offset 0–50,000, optional group_by=host |
PATCH /subjects/{subjectId} | Decision/note with current body version; this does not use If-Match |
GET /history | Optional subject, offset 0–100,000; 50 newest events per page |
PUT /timezone | IANA timezone and current body version; manager only |
POST /assets/{assetKey}/enrich | Catalogue association for a stored observation, no asset request |
GET /controls | Read up to 100 historical control records, optionally filtered by asset |
Use returned totals, partial, observation dates, evaluation completeness and filter_options to interpret inventory coverage. An absent observation is not evidence that an asset is secure or absent. Badge search criteria apply to the search surface; they do not imply an additional scope filter.
Service decisions use new, investigating or acknowledged. An acknowledged decision records a conclusion: kept, closed, updated, not_concerned or other. closed/updated requires according_to; not_concerned/other requires a note. An optional announced_date is a nonfuture YYYY-MM-DD date interpreted in the scope timezone. These are attributed declarations. They do not delete the original observation, and a later observation can reopen the subject. renewal applies to domain-expiry subjects.
Catalogue coverage and retained evidence
Each service's coverage separates three facts: availability of an evaluation (state, reasons, eligible), the displayed result (result_state, result_at, retained_result) and the latest attempt or actual processing (last_attempt_at, processing). Older deployments and frozen reports can lack these new fields.
coverage.state | Meaning |
|---|---|
evaluated | A complete catalogue evaluation is available; this can include a match |
no_identifiers, imprecise_identifiers, identifier_limit | Missing, insufficiently precise or too many software identifiers |
not_evaluated | No usable evaluation has been recorded |
catalogue_unavailable, catalogue_incomplete | Catalogue data could not support a complete evaluation |
processing_error | A corresponding evaluation task failed before a result was available |
shared_edge | Shared infrastructure is excluded from these service coverage counts |
result_state is kev, matched, no_match or indeterminate. A failed refresh does not turn an old negative into a current clean result: it becomes indeterminate. Positive evidence may remain visible with retained_result: true; its result_at is distinct from last_attempt_at. evaluation.last_attempt can also contain the recorded reasons and retained_result. A complete catalogue result is still not an active vulnerability check.
processing.state is idle, paused, unknown, queued, retry_scheduled, running, interrupted, failed or cancelled. Queue and job fields come from an actual task corresponding to the current evaluation input. A legacy task that cannot be associated reliably is unknown. available_at is a queued task's eligibility time, not a completion deadline. Reading the inventory creates no job.
Filter with evaluation=coverage:catalogue_unavailable, for example. summary.coverage contains services, excluded_shared_edge and counts by states and processing. Shared-edge observations are counted separately. A KEV subject's optional observed_products lists only {vendor, product, version} entries associated with its findings.
Frozen reports
GET /reports lists up to 100 summaries. POST /reports freezes the current view and returns 201 with a report; GET /reports/{reportId} reads its saved document under current permissions. The snapshot includes the organization/scope names, author, timezone, reference time, observations and at most 500 history entries. history_partial identifies a truncated history. Limits are 100 frozen reports per scope and 16 MiB per document.
Freezing a report does not run a search, scan an asset, publish a guest link or send email. The saved document remains the view at its recorded time; opening it does not substitute today's inventory.
Observation refresh and email preferences
PUT /monitoring takes {"enabled":true} or false and changes scheduled observation watches. POST /run takes a stable key of 16–64 characters for an observation refresh; cadence, billing and quotas apply. These operations read existing Profundis datasets.
GET /notifications reads the scope email preference. PUT /notifications requires an owner/administrator and a body with enabled, recipients (0–20 member user IDs), language (fr or en) and current version. At least one recipient is required when enabled. Recipients must still have access; delivery rechecks eligibility and observation freshness. Preferences start disabled. Saving them is not confirmation of email delivery. Personal alert preferences and organization in-app notifications are separate systems.
Active scanning is unavailable
The dedicated active CVE scan engine is not available on staging or production. There is no launch-control endpoint in this contract. Existing control records are historical evidence only. A catalogue CVE match, KEV association, observation refresh or user declaration must never be presented as a newly executed vulnerability check. Unconfirmed discovery candidates use previously collected observations only.
Coverage of this download
The session download covers the operations above, the session twins of search and enrichment, and existing IP intelligence, pipeline, portfolio and favicon-extraction tools. The public caller-IP route is explicitly unauthenticated. Account/login flows, checkout, personal alert-rule management and remaining workspace collaboration/administration routes are not yet modeled in this download; use their dedicated guides. It must not be used as a complete account or organization SDK contract.