Push ingest: contract and evaluation
Manual · API and availability · Set up data sources · Adapters
This reference applies to the push extension after v1.25.0. Machine-readable schemas are in your instance's OpenAPI specification. For initial setup, follow the data source guide.
Endpoints
Base path on your instance: /api/v1/integrations. Authentication, request size and rate limits are described in the API guide. Write requests require Content-Type: application/json.
| Method | Path relative to base path | Purpose / scope |
|---|---|---|
| GET | /identity |
Key ID and assigned sources; ingest:write |
| GET | /sources |
Source list; integrations:read |
| POST | /sources |
Create source; integrations:manage and domain permissions |
| GET | /sources/{id} |
Configuration and freshness; integrations:read |
| PUT | /sources/{id} |
Update complete configuration with revision; integrations:manage and domain permissions |
| GET | /sources/{id}/bindings |
Bindings and missing status; integrations:read |
| POST | /sources/{id}/bindings |
Explicit binding and field ownership; integrations:manage and domain permissions |
| POST | /sources/{id}/batches |
Atomic import; source-bound key with ingest:write |
| GET | /sources/{id}/observations |
Evidence metadata; integrations:read |
| GET | /sources/{id}/observations/{childId} |
Evidence with decrypted content; integrations:read |
| GET | /sources/{id}/deviations |
Deviation list; integrations:read |
| GET | /sources/{id}/deviations/{childId} |
Deviation including reason; integrations:read |
| PUT | /sources/{id}/deviations/{childId} |
Case decision; integrations:manage |
| GET | /sources/{id}/deviations/{childId}/decisions |
Immutable decision history with decrypted reasons; integrations:read |
Domain permissions for sources and bindings: assets:read plus assets:write, or backup-jobs:read plus backup-jobs:write. Linking a measure additionally requires measures:read and measures:write.
Lists return { "items": [], "offset": 0, "limit": 100 }. offset starts at 0; limit is between 1 and 100, defaulting to 100. To read all results, increase the offset by the page size until a shorter or empty page is returned. All path IDs are UUIDs.
Source configuration and binding
| Field | Contract |
|---|---|
name |
Non-empty, up to 200 characters |
apiKeyId |
UUID of the assigned adapter key |
enabled |
Boolean |
objectKind |
asset or backup_job; immutable after creation |
coverage |
Non-empty, up to 200 characters; immutable after creation |
expectedIntervalHours |
1 to 8760 hours |
missingGraceHours |
0 to 8760 hours |
createAssets |
null or defaults for new assets: ownerId, criticality (integer 1 to 5), assetType, managedFields; only for asset |
rules |
Booleans rpo, restore, sourceStale; backupFailures as integer 1 to 20 or null |
Allowed assetType values: server, database, service, software, network, cloud_service, other. managedFields contains only name, location, ip_address, os_platform, at most four entries. All configuration fields are required; unknown fields are rejected.
A binding contains externalId (non-empty, up to 200 characters), targetId (UUID) and managedFields. Existing bindings must retain their target. Source creation returns { "id": "UUID", "revision": 1 }; updates use { "revision": 1, "source": { ... } } and return the incremented revision. Read responses place rules and domain defaults under config, alongside timestamps such as last_received_at and last_observed_at.
Batch contract
Example for an already bound asset source with compliance evidence. Replace UUID, source revision, coverage, timestamps and external ID with actual values:
{
"schemaVersion": 1,
"batchId": "8d2ce318-9ab1-4e50-b715-94e690c1d250",
"sourceRevision": 1,
"coverage": "site-a-managed-assets",
"mode": "delta",
"observedAt": "2026-09-19T08:00:00Z",
"totalObjects": 1,
"objects": [
{
"externalId": "device-123",
"observations": [
{
"eventId": "device-123-compliance-20260919T080000Z",
"checkType": "device_compliance",
"result": "passed",
"observedAt": "2026-09-19T08:00:00Z",
"validUntil": "2026-09-20T08:00:00Z",
"evidence": { "summary": "The assigned device policies are satisfied." }
}
]
}
]
}
| Field | Contract |
|---|---|
schemaVersion |
Currently exactly 1 |
batchId |
UUID, persist before first delivery |
sourceRevision, coverage |
Must match current source configuration |
mode |
delta for partial delivery, full for the entire configured coverage |
observedAt |
Collection time with time zone; no more than five minutes in the future |
totalObjects |
Exact length of objects, including 0 |
objects[].externalId |
Stable ID, non-empty, up to 200 characters, unique within the batch |
objects[].asset |
Optional; required for creation. Required name, up to 200 characters; optional location, ip_address, os_platform, each up to 200 characters or null |
objects[].observations |
Required array; may be empty |
Per-request limits: 1 MiB JSON, 500 objects, 1000 observations in total, at most 20 observations per object. Unknown fields are rejected. A full batch cannot be assembled across multiple requests. The count validates only the request's contents, not the completeness of the vendor query.
All changes in a batch are accepted or rolled back together. Success returns HTTP 200:
{
"batchId": "8d2ce318-9ab1-4e50-b715-94e690c1d250",
"objects": [{ "externalId": "device-123", "targetId": "UUID-IN-ISMS-LITE" }],
"observations": 1
}
observations counts newly inserted observations. Identical known events are not stored again.
Observations and evidence
| Field | Contract |
|---|---|
eventId |
Immutable event ID within the source, up to 200 characters |
checkType |
backup_point, backup_run, restore_test, device_compliance, config_backup |
result |
passed, failed or unknown |
observedAt |
Actual observation time with time zone, no later than batch time |
validUntil |
Later than observedAt, no more than 366 days afterwards |
restorePointAt |
Optional or null, no later than the observation; required for backup_point with passed |
evidence.summary |
Non-empty summary, up to 4000 characters |
evidence.reference |
Optional HTTPS link, up to 2000 characters |
evidence.sha256 |
Optional SHA-256 checksum as 64 lowercase hexadecimal characters |
Evidence content is stored encrypted and decrypted on authorised detail access; reads are audited. The server does not fetch linked content or independently verify the claimed hash of an external file. The operator is responsible for external evidence availability and retention. Store document files through the domain API; do not include raw logs, backups, configurations or secrets in summaries.
Retries, ordering and full snapshots
Retrying the same batchId with identical content returns the original result. Reusing the ID with different content causes batchConflict. Identical eventId and event content may recur in later batches. Changed content under the same event ID causes eventConflict.
New assessments require new event IDs and new observation times. An object/check type/time combination must not become ambiguous through another event. Late evidence remains in history without replacing a newer assessment.
A new full snapshot must be later than the last accepted full snapshot. Missing objects are marked only after a successful full batch and the configured grace period. A late delta does not undo a newer missing marker. The domain asset status is not automatically set to decommissioned.
Evaluation rules
ISMS Lite evaluates on import and approximately every minute. It separates the assessment passed / failed / unknown from the case's processing state.
| Rule | Evaluation |
|---|---|
rpo |
Requires an enabled rule, asset binding and configured asset RPO. Compares the age of a valid restore point reported as usable against RPO: exceeded = failed, within target = passed. Without a valid usable point = unknown. |
restore_test |
With restore enabled, uses the latest evidence result; missing or expired = unknown. |
backup_failures |
The configured number of latest consecutive valid failures yields failed. Latest valid success = passed; insufficient failure count or unclear data = unknown. |
source_stale |
With the rule enabled, exceeding expectedIntervalHours since the last observation yields unknown; without an observation, time starts at source creation. |
object_missing |
Not seen after a full snapshot and the grace period = unknown. |
target_deleted |
Domain target deleted = unknown; history remains. |
device_compliance, config_backup |
Latest delivered result; expired = unknown. No such evaluation before the first observation of that type. |
Expired evidence does not remain successful. A failed backup job does not prove an RPO violation. Assessment of actual restore point age is separate from the existing domain check of a configured backup interval.
Handle deviations
failed and unknown can create an integration case. There is at most one active case per source, object and rule. It is neither an audit finding nor a BCM exercise.
state |
Meaning |
|---|---|
open |
Failure or unknown state persists |
recovered |
Technically passed again; domain closure is pending |
closed |
Authorised closure with a reason |
A failure before closure reopens the same case. After closure, another deviation may create a new case. Send all four fields to PUT /sources/{id}/deviations/{childId}:
{
"state": "keep",
"measureId": null,
"exceptionUntil": null,
"reason": "Investigating the cause; next assessment after the scheduled run."
}
keep retains the processing state. measureId links an existing measure; null removes the link. Create a measure through the domain API first if needed. exceptionUntil sets a justified future exception, at most 365 days from the decision; null removes it. excepted indicates an active exception while the assessment remains visible. reason is required and limited to 4000 characters. Read existing links and exceptions before editing and deliberately include any that should remain.
state: "close" closes a recovered case after review. An active case may be closed only when its source or applicable configurable rule has been disabled. Closed cases cannot be edited further. Decisions and reasons remain encrypted in immutable history under /decisions.
Neither recovery nor closure accepts a risk, approves a control or completes a measure. Automatic creation or completion of measures is not included.
Resolve conflicts
Integration errors use, for example, HTTP 409, code: "conflict" and details.reason. This table lists reason values, not separate error codes.
details.reason |
Action |
|---|---|
sourceRevision |
Read the current source; check revision and coverage. Keep already accepted batches unchanged. |
batchConflict |
Batch ID was reused differently. Resend the original file or generate a new ID for a new delivery. |
eventConflict |
Event content changed after import. Preserve the original event and report a new assessment as a new event. |
observationTimeConflict |
Object, check type and time already belong to another event. Check event identity and actual observation times. |
oldSnapshot |
Full snapshot is not later than the previous one. Collect an actually new complete snapshot. |
bindingRequired |
Bind an existing target or configure authorised asset creation for an asset source. |
manualFieldConflict |
Review the manual change and deliberately correct field ownership in the binding. |
targetDeleted |
Do not reimport the deleted target; use a new source identity for intentional recreation. |
deviationActive |
Close only recovered cases or cases explicitly removed from evaluation; leave closed cases unchanged. |
exceptionDate |
HTTP 400: exception must be in the future and no more than 365 days away. |
A domain conflict rolls back the entire batch without a partial import. Repeating an unchanged 400 or 409 does not fix the cause. For an uncertain transport response, however, resend the same persisted file.