Observations

An observation is one record of one integration operation: an HTTP API call, a webhook, a queue publish or consume, or a scheduled import or export. It captures what happened (transport result, timing, attempt, business outcome) and what the data looked like structurally, without ever containing the data itself.

Every unique, successfully persisted observation counts toward the workspace's monthly observation usage, whether the operation is healthy or unhealthy. Invalid rejected envelopes do not count. Re-delivering the same eventId does not count again. A genuine retry recorded with a new event id is a separate observation. The workspace Observations page lists this evidence and its usage; the Observation API exposes the same read boundary for automation.

Redacted by default

The collector creates structural evidence inside your process. The envelope schema has no field for payload bodies or headers, so Seamward cannot receive them even by accident.

One observation, concretely

A webhook that created a candidate produces an envelope like this:

Code example

{  "envelopeVersion": "0.2",  "eventId": "evt_01J8ZQ4X2KD9",  "integrationId": "sw_int_c9K2mQ7xLp4wR8tZ",  "direction": "inbound",  "protocol": "http-webhook",  "occurredAt": "2026-08-15T09:24:11.000Z",  "operationIdentityVersion": "1",  "eventType": "candidate.create",  "deployment": {    "service": "candidate-api",    "release": "2026.08.15",    "commitSha": "9f831da"  },  "correlation": {    "sourceEventIdHash": "sha256:5f3a...",    "hashNamespace": "candidate-api-key-2026-08"  },  "contract": { "observedFingerprint": "sha256:9c4f..." },  "transport": {    "method": "POST",    "routeTemplate": "/webhooks/candidates",    "payloadLocation": "message",    "statusCode": 202,    "durationMs": 48,    "attempt": 1  },  "payload": {    "storage": "none",    "schemaFingerprint": "sha256:9c4f...",    "schemaShape": {      "kind": "object",      "fields": {        "candidateId": { "kind": "string" },        "status": { "kind": "string" }      }    },    "redactionPolicyVersion": "candidate-api-v1"  },  "outcome": {    "accepted": true,    "businessObjectType": "candidate",    "businessObjectIdHash": "sha256:8d2c..."  }}

Read it bottom-up and the model is clear: the outcome says what the operation achieved in business terms; the payload carries structure and a fingerprint, storage: "none" recording that the body was dropped in your process; the transport says how the wire behaved; the deployment ties it to the code version that handled it. Every field is specified in the observation envelope.

The same envelope version represents every shipped protocol. HTTP observations use a method and stable route path. Queue and scheduled-feed wrappers use a compatibility projection in which the queue or feed label occupies routeTemplate, method is POST, and payloadLocation is message. A status of 0 is reserved for an attempt that received no protocol response; it is stored as transport_error, not mistaken for an HTTP code.

Correlation without exposure

Observations connect to later evidence through hashes, not identifiers:

  • traceId follows a request across your services (trace ids are operational, so they travel as-is).
  • sourceEventIdHash and idempotencyKeyHash are keyed hashes computed in your process; expected-outcome evaluation matches on the hash, so a "payment created" event and its "ledger updated" result link up without either side revealing the payment id.
  • deployment.commitSha and release let an investigation say "this shape appeared two minutes after release X" instead of guessing.

Collection failures stay yours to ignore

Collection is fail-open by construction:

  • Your handler's result or error is authoritative; observation happens after the operation and never replaces a response.
  • If Seamward is unreachable, evidence queues in bounded memory, retries on each flush, and eventually drops oldest-first. Your application never waits and never sees an error.
  • The only signals are counters on stats(); nothing is ever logged on your behalf.

What observations feed

Retention and usage

Evidence rows follow the workspace retention setting. Usage accounting is kept separately, so deleting expired evidence does not rewrite the historical total for that UTC calendar month. The Observations page and workspace API report this workspace's usage; account owners can see the shared account total when creating a workspace or through the account usage session API. Seamward reviews sustained account usage without applying an automatic overage charge.

Sandbox and Live shadow accounting

The compatibility bridge measures new usage by mode through the shadow usage API. Development and Staging classify as Sandbox; Production classifies as Live. Classification follows the authenticated connection's stored environment.

Shadow counters do not change the current plan allowance or retention setting. Historical totals that cannot be classified remain unclassifiedCount, rather than being inferred from evidence that may have expired. New workspaces have separate Sandbox and Live connections. Existing Development, Staging, and Production records stay in their original environments until reviewed cutover. The approved Sandbox policy is 10,000 observations per account per UTC month with prospective seven-day evidence retention. Enforcement remains off until the published grace period and reviewed activation. The console's Test mode switch shows a banner while Sandbox is selected.