Workspace API
A workspace-scoped HTTP API for automation. Integration inventory, observation evidence reads, usage, contract lifecycle, and explicit mode-scoped incident and repair provenance reads are available.
Choose a mode and scope
Incident and repair reads require an explicit mode=sandbox or mode=live.
Use incidents:read for incident reads and repairs:read for proposal
provenance. Existing observation keys do not acquire either permission.
Status
Integration inventory is available below. Observation list, detail, and usage endpoints are available through the Observation API. Contract registration, inspection, and activation are available through the Contract API. Workspace API keys are hashed, expiring, revocable credentials with explicit scopes. Browser session cookies do not authenticate /v1 routes.
Console session workspace management
These routes serve the signed-in console and require an authenticated, email-verified browser session. They are separate from the workspace API key routes under /v1. A workspace API key cannot create another workspace. Public automation for account-level creation is not available.
| Method and path | Result |
|---|---|
GET /workspaces | Lists every workspace membership of the signed-in user, independent of plan limits. Includes archived memberships and canManageLifecycle for account administrators who also own the workspace. |
POST /workspaces | Creates a workspace and owner membership under an account the user owns or administers. If the user has no account, creates their first Developer account. |
GET /billing-accounts | Lists accounts the user owns or administers, with the active workspace count. |
GET /billing-accounts/{accountId}/usage | Returns the account's UTC calendar-month observation total, limit, remaining count, and per-workspace contributions. |
POST /workspaces/{workspaceSlug}/archive | Archives a workspace owned by the account. New ingestion and customer writes stop. |
POST /workspaces/{workspaceSlug}/restore | Restores an archived workspace if the current plan permits it. |
Create with Content-Type: application/json and a body such as:
Code example
{ "name": "Hired by Code", "billingAccountId": "ba_example" }name must contain 2 to 80 characters. billingAccountId is required when the user administers more than one account. An optional lowercase slug can be supplied; otherwise the service derives one from the name. Success returns 201 with the workspace summary:
Code example
{ "workspace": { "id": "org_example", "tenantId": "ten_example", "name": "Hired by Code", "slug": "hired-by-code", "role": "owner", "active": false, "environments": [ { "id": "env_sandbox", "name": "Sandbox", "slug": "sandbox", "category": "sandbox", "isDefault": true }, { "id": "env_live", "name": "Live", "slug": "live", "category": "live", "isDefault": false } ] }}The console activates the workspace after the create request commits, so a failed activation does not undo the workspace.
Creation errors use stable {"error":"code"} bodies: unauthenticated (401); email_verification_required (403); account_not_found (404); invalid_workspace_name, invalid_workspace_slug, invalid_billing_account_id, account_required (400); account_unavailable, workspace_limit_reached, workspace_slug_unavailable (409); and workspace_creation_rate_limited (429, with Retry-After). The Developer limit is three active workspaces per account. The server checks the account role and limit inside the creation transaction; it never accepts a caller-supplied owner role, tenant ID, or plan.
Archival preserves evidence and audit history. The restore route checks the current account entitlement. A workspace owner who also owns or administers its account can archive it in workspace Settings and restore it from the switcher or the no-workspace recovery screen. Both routes return {"workspace":{"slug":"...","status":"archived"}} or status:"active" on success. A missing workspace or insufficient permission returns workspace_not_found (404); a restore above the Developer cap returns workspace_limit_reached (409); an unavailable account returns account_unavailable (409).
Read one workflow
GET /v1/integrations/{workspaceIntegrationId} requires integrations:read. Pass the shared wint_ workflow ID. The response contains model: "canonical" and an integration with the same fields and independent Sandbox and Live slots as canonical inventory. A not_configured slot has no connection ID, credential state, or observations. It is available for separately reviewed connection setup.
Code example
curl 'https://api.seamward.com/v1/integrations/wint_example' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"Code example
{ "model": "canonical", "integration": { "id": "wint_example", "name": "Candidate events", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook", "createdAt": "2026-09-28T12:00:00.000Z", "revision": "1", "connections": { "sandbox": { "status": "configured", "mode": "sandbox", "environmentId": "env_sandbox", "connectionId": "int_example", "revision": "1", "credentialStatus": "active", "activeContractVersionId": null, "latestObservationAt": null, "openIncidentCount": 0, "observationState": "waiting_for_observation" }, "live": { "status": "not_configured", "mode": "live", "environmentId": "env_live" } } }}The response is private and uncached. Revisions are opaque decimal strings, not edit counts. The endpoint returns unauthenticated (401), insufficient_scope (403), integration_not_found (404, including foreign identities and runtime int_ IDs), or workspace_modes_unavailable (409). Legacy topology retains the compatibility inventory until migration.
Read one connection
GET /v1/connections/{connectionId} requires a workspace API key with
integrations:read. Use the runtime int_ connection ID returned by creation or
inventory, rather than the shared wint_ workflow ID.
Code example
curl 'https://api.seamward.com/v1/connections/int_example_live' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"Code example
{ "id": "int_example_live", "workspaceIntegrationId": "wint_example", "name": "Candidate events", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook", "environment": { "id": "env_live", "category": "live", "mode": "live" }, "revision": "12", "credentialStatus": "active", "activeContractVersionId": null}The server returns the exact stored environment identifier. Legacy identifiers
remain exact targets; their classified mode grants no additional access. The
monotonic revision changes with connection configuration. credentialStatus
is not_issued, active, or revoked; it describes credential lifecycle and
does not prove application traffic. The response contains no token, token hash,
or private key. It is never cached.
Errors: unauthenticated (401), insufficient_scope (403),
connection_not_found (404, including another workspace's connection), and
workspace_modes_unavailable (409). Refresh inventory to select a current
connection after a 404. Resolve unsupported topology before retrying a 409.
Local MCP setup using a raw workspace API key requires this discovery endpoint before recording remote setup evidence. A missing endpoint, mismatched connection ID, or unsupported mode fails closed. Upgrade the server and renew the setup review before retrying. A mode or connection-key change after review requires a new review.
Connection credential lifecycle
These workspace API endpoints manage only the selected canonical Sandbox or
Live connection. Every endpoint requires integrations:manage, including
status and verification. Use a runtime int_ connection ID. A shared wint_
workflow ID is not a connection. Existing legacy connections keep their console
credential flow until reviewed migration.
| Operation | Endpoint |
|---|---|
| Current status | GET /v1/connections/{connectionId}/credentials |
| Issue a token | POST /v1/connections/{connectionId}/credentials/issue |
| Rotate a token | POST /v1/connections/{connectionId}/credentials/rotate |
| Revoke a token | POST /v1/connections/{connectionId}/credentials/revoke |
| Verify credentials | POST /v1/connections/{connectionId}/credentials/verify |
| Recover a receipt | GET /v1/credential-operations/{operationId} |
Read current status before reviewing a change:
Code example
curl 'https://api.seamward.com/v1/connections/int_example/credentials' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"Code example
{ "credential": { "connectionId": "int_example", "environmentId": "env_sandbox", "mode": "sandbox", "revision": "1", "status": "active", "issuedAt": "2026-09-28T12:00:00.000Z", "revokedAt": null }}status is not_issued, active, or revoked. The revision is an opaque
string covering connection configuration, including credential changes. A
status read contains no token or hash and does not prove application traffic.
Issue, rotate, and revoke require a JSON body containing only
expectedRevision and an Idempotency-Key with 8 to 128 printable non-space
ASCII characters. Retain both for recovery. Issue rejects an active credential;
rotation is explicit and rejects a connection that has never had a credential.
Revoking an already revoked or unissued connection records an unchanged receipt.
Code example
curl 'https://api.seamward.com/v1/connections/int_example/credentials/rotate' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: candidate-sandbox-rotate-001' \ -d '{"expectedRevision":"1"}'A first successful operation returns 201, operationId, action, the
committed credential state, connectionKey, replayed:false,
historical:false, and credentialRecoveryRequired:false. Issue and rotate
also return ingestToken exactly once. Store it securely. Revocation returns
no token. Rotation replaces the old token immediately; revocation stops writes
using that credential. The other mode's credentials and evidence are unaffected.
Retry the identical request with its original key and authorization. Success
returns 200, the original receipt, and replayed:true, without a token.
credentialRecoveryRequired:true on issue or rotation means the receipt cannot
recover the token. Read current status and review a separate rotation if the
token was lost. Never automatically retry a stale change with a newer revision.
Read a receipt through /v1/credential-operations/{operationId} under the same
workspace API key that performed the operation. It survives connection deletion
and subsequent configuration changes. historical:true means the connection no
longer has the receipt's recorded revision or has been deleted. A receipt is
evidence of the original operation, not a current health or credential verdict.
Replaying a receipt never recreates a connection or changes a token.
Verification accepts only connectionKey and ingestToken in its JSON body:
Code example
{ "connectionKey": "sw_conn_v1.K7mP4xQ9vT2nW6cR.example", "ingestToken": "sw_ing_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}These are synthetic placeholders. Supply your private token through a secret
store and avoid request-body logging. Verification returns 200,
status:"connection_verified", current credential, and
applicationVerified:false. It writes no observation, issues no token, and
does not start the application. A mismatched or revoked token returns 409.
For a collector's signed, token-only check, use
Check collector connection.
All responses use Cache-Control:no-store. Current workspace and key
authorization are checked inside the transaction and again after credential,
receipt, and audit writes before commit. A key expiring during the operation,
permission loss, or a changed authorization epoch rolls back all three writes.
An authorization change later restored still invalidates the operation.
Receipts and audit metadata never contain plaintext ingest tokens.
Canonical connections reject the legacy browser credential mutation routes
with 409 and canonical_credential_required. Use the reviewed connection
credential endpoints above. The compatibility status and Connection key reads
recheck current owner or admin access and return no token. These browser routes
do not accept a workspace API key. A request key already used by legacy
credentials, setup, deletion, or another canonical operation returns
idempotency_conflict; recovery must retain the original namespace and request.
| Status | Error | Recovery |
|---|---|---|
| 400 | invalid_credential_request | Correct the body. Unknown fields and caller-supplied tenant or mode are rejected. |
| 400 | idempotency_key_required | Retain a valid key for the mutation and its identical retries. |
| 401 | unauthenticated | Authorize with a current workspace key for an active workspace. |
| 403 | insufficient_scope | Use the original key with current integrations:manage authorization. A key revoked or expired before or during the transaction also returns this error. |
| 404 | connection_not_found | Refresh inventory. Foreign workspace IDs are also undisclosed. |
| 404 | operation_not_found | Use the original key and operation ID. Other keys cannot recover the receipt. |
| 409 | workspace_unavailable | Restore the workspace or resolve its organization binding before a new operation. |
| 409 | workspace_modes_unavailable | Resolve canonical migration before using these endpoints. |
| 409 | connection_configuration_changed | Configuration or authority changed. No token change commits. Read and review current state before creating a new operation. |
| 409 | credential_already_issued | Review rotation explicitly rather than issuing over an active credential. |
| 409 | credential_not_issued | Issue a credential before attempting rotation. |
| 409 | credential_verification_failed | Check the exact Connection key and current private token. |
| 409 | idempotency_conflict | Restore the original action, body, and authorization, or deliberately start a new reviewed operation. |
Create an Integration and first connection
Code example
POST /v1/integrationsCreate a new workflow and its first connection atomically. Select sandbox or
live explicitly. A workspace API key needs integrations:manage. Connections
with the same name remain independent workflows. Set up the other mode through the reviewed connection lifecycle below.
Code example
curl 'https://api.seamward.com/v1/integrations' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: candidate-events-create-001' \ -d '{"mode":"sandbox","name":"Candidate events","provider":"ATS","direction":"inbound","protocol":"http-webhook"}'| Field | Required | Meaning |
|---|---|---|
mode | Yes | sandbox or live; there is no default or legacy alias. |
name | Yes | Workflow name, trimmed to 1 to 120 characters. |
provider | Yes | Provider identity, trimmed to 1 to 120 characters. |
direction | Yes | inbound or outbound. |
protocol | Yes | http-api, http-webhook, scheduled-feed, or queue. |
Unknown fields are rejected. Workspace and organization come from the key. An environment identifier, tenant identifier, or existing Integration identifier cannot override the authenticated target.
Success returns 201, replayed:false, and credentialRecoveryRequired:false.
integration.id is the shared workflow ID; integration.connectionId is the
runtime connection ID. integration.mode and integration.environmentId identify
the selected mode. collectorConfiguration.connectionKey and
collectorConfiguration.ingestToken configure that connection. Store the token
securely when it is returned. No contract is activated and
connectionState:"waiting_for_observation" does not prove traffic has arrived.
Retry an identical request using the same key and the original authorization.
The result is 200, replayed:true, and credentialRecoveryRequired:true.
The response includes the original Integration, operation ID, and connection
key, but never the token. A lost token requires a separately approved credential
rotation through the connection credential API.
The console provides credential controls and receipt recovery. A retry does not recreate a deleted connection; the
receipt describes the original operation. Use a new idempotency key only when
intentionally creating another workflow.
Read a saved receipt without retrying creation:
Code example
GET /v1/integration-operations/{operationId}Code example
curl 'https://api.seamward.com/v1/integration-operations/connop_example' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"This GET requires integrations:manage on the same key that created the
operation. It returns the credential-free replay shape above. A malformed,
missing, or differently authorized operation returns operation_not_found
(404), without disclosing the other workflow. Missing authorization returns
401 and missing management scope returns 403. Current authority is revalidated
inside the receipt transaction; archival or rebinding during an admitted request
returns workspace_unavailable (409). A key presented after archival fails
public authentication with 401. A saved receipt remains historical after the
connection is deleted.
Both responses use Cache-Control:no-store. Receipts and audit metadata contain
no plaintext ingest token. Revoked credentials, expired credentials, lost
management scope, and archived workspaces cannot execute the transaction.
Creation rechecks matching current authority after identity, connection, receipt
and audit writes before commit. Expiry or permission loss rolls everything
back. workspace_authorization_changed means the authority epoch changed during
creation, even if its permissions were later restored. Review current access
and deliberately start a new operation.
| Status | Code | Recovery |
|---|---|---|
| 400 | invalid_integration | Correct the body and use a canonical mode. |
| 400 | idempotency_key_required | Supply 8 to 128 printable non-space ASCII characters. |
| 401 | unauthenticated | Authorize with a valid, unexpired workspace API key. |
| 403 | insufficient_scope | Issue a key with integrations:manage; retry only with the original binding. |
| 409 | workspace_authorization_changed | Refresh and review current permissions before a new creation attempt. |
| 409 | workspace_modes_unavailable | Ask the workspace operator to complete migration or repair the canonical pair. |
| 409 | workspace_unavailable | Restore or reauthorize the workspace before creating a connection. |
| 409 | idempotency_conflict | Restore the identical request and original authorization, or deliberately create a new workflow with a new key. |
Existing legacy workspaces must continue their exact-target setup flow until
migration. This endpoint does not migrate their environments, credentials, or
evidence. Malformed JSON and requests larger than 1 MiB return the common
invalid_request and request_too_large errors.
Set up the other mode connection
The public API can create a missing Sandbox or Live connection for an existing workflow. In the console, select Set up Sandbox or Set up Live on a workflow that has a missing mode connection. Start empty or select declared contracts and expected outcome rules from the other mode, review the snapshot, then apply it. Copied contracts remain drafts and copied rules remain disabled. For an already configured destination, use reviewed configuration copying. Changing the console mode switch alone does not invoke either API or provision a connection.
Use the original workspace API key with integrations:manage throughout review,
apply, and status. Start with the shared wint_... ID from creation or
List Integrations. A runtime int_... ID is not a shared
workflow identifier.
Completed operation URLs recover a credential-free receipt. The console checks the receipt against the current mode connection. A removed or replaced connection is labelled historical and does not display active Collector setup. Copy audit metadata records each source artifact and its destination ID, along with the operation, source revision and destination connection.
Preview
Code example
POST /v1/integrations/{workspaceIntegrationId}/connections/previewFor an empty independent Live connection:
Code example
curl 'https://api.seamward.com/v1/integrations/wint_example/connections/preview' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"destinationMode":"live","contractVersionIds":[],"ruleIds":[]}'To copy selected configuration, add sourceConnectionId, contractVersionIds,
and ruleIds. The source must be the other canonical mode connection of the
same shared Integration in the same workspace. Find declared contract IDs
through List contracts. Use List connection rules to discover exact source rule IDs.
Code example
{ "destinationMode": "live", "sourceConnectionId": "int_example_sandbox", "contractVersionIds": ["cv_candidate_v1"], "ruleIds": ["rule_candidate_created"]}Both selection arrays default to empty and allow at most 100 identifiers each.
The complete snapshot must fit within 1 MiB; reduce the selection if needed.
Copy selections require an explicit source. Duplicate, unavailable, inferred,
and conflicting contract versions are rejected. Unknown fields are rejected.
The response is 201 with operationId, status:"previewed", fingerprint,
expiresAt, and a whitelisted snapshot. Review the exact identity, source
revision, destination, contract schemas, and rule definitions in that snapshot.
The fingerprint binds the snapshot, authorization, operation, and expiry.
The review lasts ten minutes. Server time starts the window and prevents a delayed request from extending an expired review. No connection or credential is issued at this step. Preview and apply are audited. Contracts will be drafts and copied rules will be disabled. Credentials, baselines, observations, incidents, replay data, repair proposals, approvals, and delivery results cannot be copied. There is no automatic synchronization with later source edits.
Apply
Code example
POST /v1/connection-setup/{operationId}/applyAfter reviewing the server-returned snapshot, use its exact operation ID and
set SEAMWARD_APPROVAL_FINGERPRINT to the returned fingerprint. A fingerprint
copied from an example cannot approve your operation.
Code example
curl 'https://api.seamward.com/v1/connection-setup/connsetup_example/apply' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: candidate-live-setup-001' \ -d "{\"approvalFingerprint\":\"$SEAMWARD_APPROVAL_FINGERPRINT\"}"First apply returns 201, status:"completed", the shared workflow and new
runtime connection, and one-time collectorConfiguration values. Save the new
Live token separately from the Sandbox token. Identical retries with the same
idempotency key return 200 and a credential-free receipt. A lost token requires
a new reviewed rotation through the
connection credential API.
The console provides credential controls and receipt recovery. Contracts are not activated by setup; use
the reviewed contract activation API.
Rule enablement remains a separate explicit action.
The server serializes retries and rechecks authorization, source revision, identity, selection, and destination absence in the write transaction. An edit followed by a reversion still invalidates review. Worker evaluation timestamps do not invalidate unchanged rule configuration. Competing previews for the same destination cannot create duplicate connections. The losing apply must review again.
Expiry and current authorization are checked again before the transaction completes. If the review or authorizing key expires during apply, or authority changes, the new connection, copied configuration, credential, completion receipt, and completion audit event all roll back. Create a fresh review after resolving the cause; an expired approval cannot be extended by retrying it.
Status and recovery
Code example
GET /v1/connection-setup/{operationId}Read with the same currently authorized key carrying integrations:manage.
The original binding and current authority are checked transactionally for
pending, expired, and completed operations. Pending operations return their review; past-expiry
operations report status:"expired". Completed operations return the historical
credential-free receipt. Status does not refresh approval or prove that traffic
has arrived. Responses use Cache-Control:no-store.
Status uses server time even when the request was delayed. Revoking or expiring the original key, removing its management scope, or archiving the workspace prevents recovery. Browser operations similarly require the original owner or admin to retain current workspace access.
| Status | Code | Recovery |
|---|---|---|
| 400 | invalid_connection_setup | Correct the request fields or approval fingerprint format. |
| 400 | configuration_scope_mismatch | Select the same workflow’s other canonical mode connection. |
| 400 | configuration_selection_invalid | Choose unique declared contract and rule IDs from the source. |
| 400 | idempotency_key_required | Supply 8 to 128 printable non-space ASCII characters for apply. |
| 401 | unauthenticated | Authorize with an active workspace API key. |
| 403 | insufficient_scope | Use the original key with current management permission. |
| 404 | integration_not_found, operation_not_found | Check the exact shared ID, workspace, and original key. |
| 409 | workspace_modes_unavailable, workspace_unavailable | Complete migration or restore workspace availability. |
| 409 | configuration_snapshot_too_large | Reduce the selected configuration to fit within 1 MiB. |
| 409 | connection_already_configured | Use a reviewed configuration copy for the existing connection. |
| 409 | approval_mismatch | Restore the exact fingerprint returned for this operation. |
| 409 | connection_preview_expired, connection_preview_stale | Request and review a fresh preview. |
| 409 | idempotency_conflict | Retry the completed operation with its original key or review a new operation. |
Copy configuration to an existing connection
Available through the workspace API. Both canonical mode connections must already exist under the same shared Integration. This operation adds selected declared contracts as drafts and selected reconciliation rules as disabled rules. It preserves credentials, the active contract, evidence and operational history. Later source changes do not synchronize. The console exposes selection, review, apply and recovery under Manage this connection.
Use the same currently authorized workspace key with integrations:manage
throughout review, apply and recovery. Find exact int_ connection IDs in
List Integrations, and source versions in
List contracts.
Review an existing destination
Code example
POST /v1/connections/{connectionId}/configuration-copy/previewCode example
curl 'https://api.seamward.com/v1/connections/int_live/configuration-copy/preview' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"sourceConnectionId":"int_sandbox","contractVersionIds":["cv_source"],"ruleIds":[]}'Replace example IDs with IDs from your workspace. Select at least one artifact.
Each array allows up to 100 unique identifiers; both default to empty. Unknown
body and query fields are rejected. The selected document projection and final
snapshot are bounded to 1 MiB. A destination contract version or rule with the
same declared version or event/object pair produces
configuration_destination_conflict. Choose a different declared version in a
separate source change, then review again.
A 201 response contains operationId (concopy_...),
action:"configuration.copy", status:"previewed", fingerprint, expiresAt
and the exact snapshot. Review source, destination, both revisions, shared
identity, contracts and disabled rule definitions. The ten-minute review binds
current authority and configuration, including edits later restored.
A complete copy preview example:
Code example
{ "operationId": "concopy_example", "action": "configuration.copy", "status": "previewed", "expiresAt": "2026-09-29T12:10:00.000Z", "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "originalOperationId": null, "snapshot": { "identity": { "id": "wint_example", "revision": "1", "tenantId": "ten_example", "name": "Candidate events", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook" }, "source": { "connectionId": "int_sandbox", "environmentId": "env_sandbox", "revision": "2" }, "destination": { "mode": "live", "environmentId": "env_live", "connectionId": "int_live", "revision": "3" }, "contracts": [ { "sourceContractVersionId": "cv_source", "declaredVersion": "candidate-v1", "signature": "{}", "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "importedFrom": "json-schema", "lifecycleStatus": "draft", "operations": [] } ], "rules": [], "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "copiedArtifacts": null}| Field | Meaning |
|---|---|
operationId, action | Exact copy or compensation operation identity. |
fingerprint, expiresAt | Approval value and server-issued ten-minute deadline. |
snapshot.identity | Shared Integration identity and monotonic revision. |
snapshot.source, snapshot.destination | Explicit connection IDs, mode and reviewed revisions. |
snapshot.contracts, snapshot.rules | Exact permitted drafts and disabled definitions. |
originalOperationId, copiedArtifacts | Null for copy review; exact original receipt and created mappings for compensation. |
Apply and recover
Code example
POST /v1/configuration-operations/{operationId}/applyGET /v1/configuration-operations/{operationId}Set SEAMWARD_APPROVAL_FINGERPRINT to the fingerprint returned by your review.
Apply its exact operation ID with a new retained Idempotency-Key of 8 to 128
printable non-space ASCII characters:
Code example
curl 'https://api.seamward.com/v1/configuration-operations/concopy_example/apply' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: candidate-live-copy-001' \ -d "{\"approvalFingerprint\":\"$SEAMWARD_APPROVAL_FINGERPRINT\"}"First apply returns 201, status:"completed", the connection, mode, committed
revision, completedAt, and source/destination artifact ID mappings in
copiedArtifacts. Identical original-key retry returns 200 with
replayed:true. A key already used by another operation is rejected. No ingest
token is issued or returned.
After an unknown outcome, read status with the original key before deciding to
retry. Pending and expired reviews remain inspectable. Completed receipts stay
immutable; historical:true means the destination changed or disappeared after
completion. A receipt proves the operation committed, not current health or
active configuration. Reads do not extend reviews. Responses are no-store.
Completed copy example:
Code example
{ "operationId": "concopy_example", "action": "configuration.copy", "status": "completed", "connectionId": "int_live", "workspaceIntegrationId": "wint_example", "mode": "live", "revision": "4", "completedAt": "2026-09-29T12:01:00.000Z", "originalOperationId": null, "proof": { "schema": "seamward.configuration-operation/1", "approvalFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "configurationFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "copiedArtifacts": { "contracts": [ { "sourceContractVersionId": "cv_source", "destinationContractVersionId": "cv_copied" } ], "rules": [] }, "replayed": false, "historical": false}proof.schema is seamward.configuration-operation/1.
proof.approvalFingerprint permanently binds the accepted review;
proof.configurationFingerprint binds its exact configuration snapshot.
Completed proofs cannot be rewritten. Pending review inputs also remain fixed.
revision is the destination epoch after the transaction, rather than the
pre-copy epoch in the review. copiedArtifacts records every created ID.
The completed status and identical retry response uses the same receipt with
replayed:true. Its proof, mappings and completion time stay unchanged.
historical is calculated from current state. A pending status has the same
preview shape; after its deadline it has status:"expired" and the original
fingerprint, snapshot and expiry. Review deadlines never refresh on reads.
Review compensation
Code example
POST /v1/configuration-operations/{operationId}/compensation-previewSend an empty JSON object {} using the original authorized key. A 201
response has a new concomp_... operation, action:"configuration.compensate",
its own fingerprint and expiry, originalOperationId, and the exact created
artifact mappings. Apply this new review through the same apply endpoint with
a new idempotency key and its returned fingerprint.
Compensation preview example:
Code example
{ "operationId": "concomp_example", "action": "configuration.compensate", "status": "previewed", "expiresAt": "2026-09-29T12:10:00.000Z", "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "originalOperationId": "concopy_example", "snapshot": { "identity": { "id": "wint_example", "revision": "1", "tenantId": "ten_example", "name": "Candidate events", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook" }, "source": { "connectionId": "int_sandbox", "environmentId": "env_sandbox", "revision": "2" }, "destination": { "mode": "live", "environmentId": "env_live", "connectionId": "int_live", "revision": "4" }, "contracts": [ { "sourceContractVersionId": "cv_source", "declaredVersion": "candidate-v1", "signature": "{}", "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "importedFrom": "json-schema", "lifecycleStatus": "draft", "operations": [] } ], "rules": [], "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "copiedArtifacts": { "contracts": [ { "sourceContractVersionId": "cv_source", "destinationContractVersionId": "cv_copied" } ], "rules": [] }}Completed compensation returns the following token-free receipt:
Code example
{ "operationId": "concomp_example", "action": "configuration.compensate", "status": "completed", "connectionId": "int_live", "workspaceIntegrationId": "wint_example", "mode": "live", "revision": "5", "completedAt": "2026-09-29T12:02:00.000Z", "originalOperationId": "concopy_example", "proof": { "schema": "seamward.configuration-operation/1", "approvalFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "configurationFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "copiedArtifacts": { "contracts": [ { "sourceContractVersionId": "cv_source", "destinationContractVersionId": "cv_copied" } ], "rules": [] }, "replayed": false, "historical": false}A completed compensation receipt has action:"configuration.compensate", its
new concomp_ ID, the original copy in originalOperationId, the exact removed
artifact mappings, its own versioned proof and the post-removal revision. Retry
and status preserve that receipt without repeating removal.
Compensation removes only the pristine draft contracts and disabled rules created by that original copy. Any later destination configuration change, including credential rotation or a rule enabled and then disabled again, makes it unavailable. Activated contracts, activation history, findings and incident references also block compensation. Credentials and existing configuration are preserved. This operation cannot restore deleted evidence or undo configuration that has been used. The original copy receipt remains readable.
| Status | Code | Recovery |
|---|---|---|
| 400 | invalid_configuration_request, configuration_selection_invalid, configuration_scope_mismatch | Correct exact IDs, unique selections and the opposite mode of the same shared Integration. |
| 400 | idempotency_key_required | Provide a retained apply key in the documented format. |
| 401, 403 | unauthenticated, insufficient_scope | Restore the original key's current management authority. |
| 404 | connection_not_found, integration_not_found, operation_not_found | Check exact workspace, target and original actor binding. |
| 409 | configuration_destination_conflict | Resolve duplicate destination definitions, then review again. |
| 409 | configuration_snapshot_too_large | Reduce selected document content or the selection. |
| 409 | configuration_preview_stale, configuration_preview_expired, approval_mismatch | Read current state and create a fresh review. |
| 409 | configuration_compensation_unavailable | Keep used configuration; review a separate explicit change instead. |
| 409 | idempotency_conflict | Recover the original operation or use a new key for a new review. |
| 409 | workspace_unavailable, workspace_modes_unavailable | Restore workspace availability or complete canonical mode migration. |
| 429 | rate_limited | Wait 60 seconds. Setup, copy and compensation share 30 previews per workspace per minute. |
Browser session adapters use the same paths under
/workspaces/{workspaceSlug} in place of /v1. They require a current owner or
admin. Only original-user completed receipt reads support
archived workspace recovery; pending
reviews and mutations still require an active workspace.
Recover a configuration operation
Identical copy retry and completed copy status return the same original receipt,
with replayed:true. The original proof, mappings, completion time and revision
are retained:
Code example
{ "operationId": "concopy_example", "action": "configuration.copy", "status": "completed", "connectionId": "int_live", "workspaceIntegrationId": "wint_example", "mode": "live", "revision": "4", "completedAt": "2026-09-29T12:01:00.000Z", "originalOperationId": null, "proof": { "schema": "seamward.configuration-operation/1", "approvalFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "configurationFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "copiedArtifacts": { "contracts": [ { "sourceContractVersionId": "cv_source", "destinationContractVersionId": "cv_copied" } ], "rules": [] }, "replayed": true, "historical": false}Compensation retry and status return the original removal receipt:
Code example
{ "operationId": "concomp_example", "action": "configuration.compensate", "status": "completed", "connectionId": "int_live", "workspaceIntegrationId": "wint_example", "mode": "live", "revision": "5", "completedAt": "2026-09-29T12:02:00.000Z", "originalOperationId": "concopy_example", "proof": { "schema": "seamward.configuration-operation/1", "approvalFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "configurationFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "copiedArtifacts": { "contracts": [ { "sourceContractVersionId": "cv_source", "destinationContractVersionId": "cv_copied" } ], "rules": [] }, "replayed": true, "historical": false}A pending review becomes expired after its ten-minute deadline. Status is still
readable by its original currently authorized actor, but applying returns
configuration_preview_expired. Review current configuration in a new operation:
Code example
{ "operationId": "concopy_example", "action": "configuration.copy", "status": "expired", "expiresAt": "2026-09-29T12:10:00.000Z", "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "originalOperationId": null, "snapshot": { "identity": { "id": "wint_example", "revision": "1", "tenantId": "ten_example", "name": "Candidate events", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook" }, "source": { "connectionId": "int_sandbox", "environmentId": "env_sandbox", "revision": "2" }, "destination": { "mode": "live", "environmentId": "env_live", "connectionId": "int_live", "revision": "3" }, "contracts": [ { "sourceContractVersionId": "cv_source", "declaredVersion": "candidate-v1", "signature": "{}", "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "importedFrom": "json-schema", "lifecycleStatus": "draft", "operations": [] } ], "rules": [], "fingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "copiedArtifacts": null}Manage connection reconciliation rules
Available through the workspace API. Rules belong to one exact Sandbox or
Live int_ connection. Use a workspace API key with integrations:read to
discover definitions, and integrations:manage for mutations and retained
receipt recovery. Source names, object types and delays are configuration;
observations and incidents are never copied or returned by these endpoints.
Discover and review
Code example
GET /v1/connections/{connectionId}/reconciliation-rulesGET /v1/connections/{connectionId}/reconciliation-rules/{ruleId}Code example
curl 'https://api.seamward.com/v1/connections/int_sandbox/reconciliation-rules?limit=25' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"The list returns exact connection context, the current revision, rules and
nextCursor. limit defaults to 25 and allows 1 to 100. Preserve the opaque
cursor on later pages of the same connection. A cursor used in another
connection is invalid; a changed configuration revision requires a fresh list.
Worker evaluation timestamps do not invalidate a configuration review.
Code example
{ "connectionId": "int_sandbox", "workspaceIntegrationId": "wint_example", "mode": "sandbox", "revision": "3", "rules": [ { "id": "rule_candidate", "sourceEventType": "candidate.created", "expectedObjectType": "candidate", "maxDelayMs": 10000, "enabled": false, "lastEvaluatedAt": null, "createdAt": "2026-09-29T12:00:00.000Z", "updatedAt": "2026-09-29T12:00:00.000Z" } ], "nextCursor": null}Single-rule reads return the same context with rule instead of rules and
nextCursor. Copy the exact revision you reviewed into expectedRevision for
any mutation. A revision from an example is not an approval of your connection.
Create or enable a rule
Code example
POST /v1/connections/{connectionId}/reconciliation-rulesPATCH /v1/connections/{connectionId}/reconciliation-rules/{ruleId}DELETE /v1/connections/{connectionId}/reconciliation-rules/{ruleId}| Field | Create | Update | Delete |
|---|---|---|---|
expectedRevision | Required reviewed decimal-string epoch | Required | Required |
sourceEventType | Required, 1 to 120 letters, digits, ., _, :, - | Optional | Rejected |
expectedObjectType | Same format, required | Optional | Rejected |
maxDelayMs | Required integer, 1,000 to 86,400,000 | Optional | Rejected |
enabled | Defaults to false | Optional explicit boolean | Rejected |
Create example:
Code example
{ "expectedRevision": "2", "sourceEventType": "candidate.created", "expectedObjectType": "candidate", "maxDelayMs": 10000, "enabled": false}Require at least one changed-definition field on PATCH; omitted fields stay
unchanged. To enable a copied disabled rule, review its current configuration,
then PATCH { "expectedRevision": "3", "enabled": true }. Setting enabled
to true affects analysis on this connection only. Test the definition in
Sandbox before explicitly enabling its separate Live copy. Copying never
enables a rule automatically.
For each mutation send JSON and a new retained Idempotency-Key of 8 to 128
printable non-space ASCII characters. Unknown fields and query parameters are
rejected. A matching source-event/object pair must be unique within the
connection. DELETE accepts only expectedRevision and refuses rules with
retained incident history. Disable such a rule with a separately reviewed PATCH
instead; incident history remains intact.
Mutation receipts and recovery
Code example
GET /v1/rule-operations/{operationId}Make a reviewed rule request
Set SEAMWARD_CONNECTION_ID to the exact connection returned by your inventory,
SEAMWARD_RULE_ID to a rule from its list, and SEAMWARD_REVIEWED_REVISION to
that list's current revision. Use a separate retained request key for each
reviewed change; keep the same key and body after a lost response.
Create a disabled definition:
Code example
curl -sS -X POST "https://api.seamward.com/v1/connections/$SEAMWARD_CONNECTION_ID/reconciliation-rules" \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H "Idempotency-Key: $SEAMWARD_RULE_CREATE_KEY" \ -H 'Content-Type: application/json' \ --data "{\"expectedRevision\":\"$SEAMWARD_REVIEWED_REVISION\",\"sourceEventType\":\"candidate.created\",\"expectedObjectType\":\"candidate\",\"maxDelayMs\":10000,\"enabled\":false}"Read current state and review its revision before enabling that exact rule:
Code example
curl -sS -X PATCH "https://api.seamward.com/v1/connections/$SEAMWARD_CONNECTION_ID/reconciliation-rules/$SEAMWARD_RULE_ID" \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H "Idempotency-Key: $SEAMWARD_RULE_UPDATE_KEY" \ -H 'Content-Type: application/json' \ --data "{\"expectedRevision\":\"$SEAMWARD_REVIEWED_REVISION\",\"enabled\":true}"To detach a rule with no incident history, review the latest revision and use its own deletion request key. Disabling is the supported alternative when history prevents deletion:
Code example
curl -sS -X DELETE "https://api.seamward.com/v1/connections/$SEAMWARD_CONNECTION_ID/reconciliation-rules/$SEAMWARD_RULE_ID" \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H "Idempotency-Key: $SEAMWARD_RULE_DELETE_KEY" \ -H 'Content-Type: application/json' \ --data "{\"expectedRevision\":\"$SEAMWARD_REVIEWED_REVISION\"}"Set SEAMWARD_RULE_OPERATION_ID to the returned operationId to recover that
original actor's receipt. After a response is lost before the ID is known,
resend the exact original body and key to recover the committed operation:
Code example
curl -sS "https://api.seamward.com/v1/rule-operations/$SEAMWARD_RULE_OPERATION_ID" \ -H "Authorization: Bearer $SEAMWARD_API_KEY"First mutation returns 201 with the committed definition, exact mode,
resulting revision and immutable token-free receipt:
Code example
{ "connectionId": "int_sandbox", "workspaceIntegrationId": "wint_example", "mode": "sandbox", "revision": "3", "operationId": "ruleop_example", "action": "rule.create", "status": "completed", "expectedRevision": "2", "requestFingerprint": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "completedAt": "2026-09-29T12:00:00.000Z", "rule": { "id": "rule_candidate", "sourceEventType": "candidate.created", "expectedObjectType": "candidate", "maxDelayMs": 10000, "enabled": false, "lastEvaluatedAt": null, "createdAt": "2026-09-29T12:00:00.000Z", "updatedAt": "2026-09-29T12:00:00.000Z" }, "replayed": false, "historical": false}Update and deletion use action:"rule.update" and action:"rule.delete".
Deletion retains the removed rule definition in its receipt. A new mutation,
receipt, redacted audit and analysis enqueue commit in the same transaction.
There is no partial commit after permission loss or a stale revision.
Keep the original operation ID, request and idempotency key. Identical successful
retry returns 200 and replayed:true. A lost response can also be recovered
with the original currently authorized actor through the status endpoint.
requestFingerprint binds the normalized exact request. historical:true
means the connection revision has since changed or the connection disappeared;
it does not assert current rule state. Proof and completion time do not change.
Responses are no-store. Another key cannot inherit a receipt.
| Status | Code | Recovery |
|---|---|---|
| 400 | invalid_rule_request, invalid_rule_cursor | Correct strict fields or restart pagination in the exact connection. |
| 400 | idempotency_key_required | Supply and retain a correctly formatted mutation key. |
| 401, 403 | unauthenticated, insufficient_scope | Use the required current workspace authority. |
| 404 | connection_not_found, expected_outcome_not_found, operation_not_found | Check exact IDs, workspace and original actor. |
| 409 | rule_cursor_stale, connection_configuration_changed | Read current state and review again. |
| 409 | expected_outcome_already_exists | Use the existing definition or review an explicit update. |
| 409 | expected_outcome_has_incident_history | Preserve history and review disabling the rule instead. |
| 409 | idempotency_conflict | Recover the original operation. Use a new key for a separately reviewed request. |
| 409 | workspace_unavailable, workspace_modes_unavailable | Restore workspace access or complete canonical mode migration. |
| 429 | rate_limited | Wait 60 seconds. The budget is 60 new mutations per workspace per minute; successful identical retries reuse their receipt. |
Console rule compatibility
The console's expected-outcome controls share the canonical rule service, current membership checks, reviewed revision, retained request key, receipt, audit and atomic analysis transaction. A stale form reports a conflict; reload and review current configuration before submitting a new request. Retrying the same uncertain submission retains its original request key.
Session reads at /workspaces/{workspaceSlug}/integrations/{connectionId}/expected-outcomes
return the displayed revision, mode, integration name, management permission
and expected outcomes. POST, PATCH and DELETE require expectedRevision and
Idempotency-Key; unreviewed requests are rejected with invalid_rule_request
(400), and a missing key returns idempotency_key_required (400). Creation returns
201, or 200 on a successful retry; updates and deletion return 200. The response
contains expectedOutcome and its completed operation.
Original-user receipts use /workspaces/{workspaceSlug}/rule-operations/{operationId}.
A current owner or admin who performed the operation can recover its completed
receipt in an archived workspace. Archived workspaces do not accept mutations.
Legacy environment records remain readable with their actual mode classification
and management controls disabled; canonical migration is required before a new
rule mutation. The deprecated POST /integrations/{connectionId}/reconciliation-rules
route rejects unreviewed mutation with canonical_lifecycle_required (409). Use
the public revision-bound lifecycle above. Existing unbound
mutation requests have no compatibility writer.
Use the public routes above for automation. Browser cookies are not workspace API keys, and a rule operation cannot be recovered by another actor.
List workspace environments
Code example
GET /v1/environmentsDiscover exact environment identifiers before selecting a target for automation.
Use an expiring workspace API key
with integrations:read. There is no request body or filter. The response is
ordered by environment ID and is not cached.
Code example
curl 'https://api.seamward.com/v1/environments' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"For a newly created workspace, success returns 200 with:
Code example
{ "model": "canonical", "environments": [ { "id": "env_live", "name": "Live", "slug": "live", "category": "live", "mode": "live", "isDefault": false }, { "id": "env_sandbox", "name": "Sandbox", "slug": "sandbox", "category": "sandbox", "mode": "sandbox", "isDefault": true } ]}| Field | Type | Meaning |
|---|---|---|
model | canonical or legacy | Canonical workspaces have exactly Sandbox and Live. Existing workspaces retain their original environments until reviewed migration. |
environments | array, 1 to 100 items | Exact stored environment records in this workspace. |
id | string beginning env_ | Exact target identifier. Do not replace an identifier based on its display name or classification. |
name, slug | nonempty strings | Display name and navigation slug. |
category | sandbox, live, development, production, or staging | Stored environment category. |
mode | sandbox or live | Classification for presentation. Development and Staging classify as Sandbox; Production classifies as Live. |
isDefault | boolean | Sandbox is the default in canonical workspaces. |
Classification does not move connections, broaden grants, or change observation
allowances. A legacy response preserves every original environment identifier.
Use its exact identifiers with integration inventory.
Setup authorization selects an existing environment and cannot create Staging.
| Status | Body | Recovery |
|---|---|---|
| 401 | {"error":"unauthenticated"} | Use a valid, unexpired workspace API key. |
| 403 | {"error":"insufficient_scope"} | Ask an administrator for a key carrying integrations:read. |
| 409 | {"error":"workspace_modes_unavailable"} | The stored topology is missing, unsupported, or mixes legacy and canonical records. Ask the workspace owner to resolve the migration state; do not guess a target. |
List Integrations
For a canonical workspace, request both independent mode slots:
Code example
GET /v1/integrations?view=canonical&limit=50Code example
curl 'https://api.seamward.com/v1/integrations?view=canonical&limit=50' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"Each item retains its shared wint_ identity, name, provider, direction,
protocol, creation timestamp, and shared revision. connections.sandbox and
connections.live each report their exact mode and environment ID. A missing
slot contains only status: "not_configured", mode, and environmentId.
It has no fabricated runtime connection, credentials, evidence, or health.
A configured slot includes connectionId, configuration revision,
credentialStatus, activeContractVersionId, latestObservationAt,
openIncidentCount, and observationState. Observation states are
waiting_for_observation, observed, and incident_open. observed establishes
accepted traffic, rather than a complete health verdict. Credentials and token
hashes are omitted.
For a workflow with an issued Sandbox connection and a missing Live connection:
Code example
{ "model": "canonical", "items": [ { "id": "wint_example", "name": "Candidate events", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook", "createdAt": "2026-09-28T12:00:00.000Z", "revision": "1", "connections": { "sandbox": { "status": "configured", "mode": "sandbox", "environmentId": "env_sandbox", "connectionId": "int_example", "revision": "1", "credentialStatus": "active", "activeContractVersionId": null, "latestObservationAt": null, "openIncidentCount": 0, "observationState": "waiting_for_observation" }, "live": { "status": "not_configured", "mode": "live", "environmentId": "env_live" } } } ], "nextCursor": null}When nextCursor is non-null, pass it unchanged as cursor with
view=canonical. limit defaults to 50 and accepts 1 through 100. Each page is
a consistent database snapshot ordered by shared ID. Separate pages may reflect
new changes; pagination does not freeze the workspace. Cursors are bound to one
workspace and cannot authorize another workspace's data. Restart without a
cursor after migration or an incompatible cursor error.
invalid_inventory_query (400) rejects an unknown view, bad limit, malformed
cursor syntax, or an environmentId filter combined with canonical view.
invalid_inventory_cursor (400) rejects an unsupported or foreign workspace
cursor. workspace_modes_unavailable (409) rejects legacy, incomplete, or mixed
topology in canonical view. Resolve the migration state before retrying it.
Unauthenticated and insufficient-scope errors remain 401 and 403.
Omitting view retains the compatible inventory response:
Code example
GET /v1/integrations?environmentId={environmentId}Use a workspace API key carrying integrations:read. The optional
environmentId filter limits each stable Integration to its connection in one
workspace environment. Without the filter, each item includes every configured
connection in the workspace, including exact legacy identifiers where they
remain. This compatible response is capped at 100 items.
Code example
{ "items": [ { "id": "wint_candidate", "name": "Candidate ATS", "provider": "HireFlow", "direction": "inbound", "protocol": "http-webhook", "createdAt": "2026-08-30T12:00:00.000Z", "connections": [ { "id": "int_candidate_development", "environmentId": "env_development", "connectionState": "observed", "structuralAnalysis": { "status": "active", "code": null, "checkedAt": "2026-08-30T12:05:01.000Z", "lastSuccessAt": "2026-08-30T12:05:01.000Z", "pausedAt": null, "reason": null, "groups": 0, "bytes": 0 }, "behavioralAnalysis": { "status": "active", "code": null, "checkedAt": "2026-08-30T12:05:01.000Z", "lastSuccessAt": "2026-08-30T12:05:01.000Z", "pausedAt": null, "reason": null, "groups": 0, "bytes": 0 }, "declaredVersion": "candidate-ats-v1", "latestObservationAt": "2026-08-30T12:05:00.000Z", "openIncidentCount": 0, "createdAt": "2026-08-30T12:00:00.000Z" } ] } ]}Each connection includes structuralAnalysis. Older server versions may omit it.
active with a null lastSuccessAt means analysis has not completed yet.
paused_capacity means structural comparison could not finish within the MVP
capacity limits; it does not mean the integration is healthy. The stable code is
structural_analysis_capacity_exceeded. reason is groups, bytes, or
findings. Counts are bounded lower bounds when a limit is exceeded, and are
zero after success. Behavioral detection and expected-outcome checks continue.
See capacity troubleshooting.
Behavioral analysis capacity
Each connection also includes behavioralAnalysis, with the same fields and state
rules as structuralAnalysis. Older servers may omit either field; absence does
not establish a completed analysis. A behavioral pause uses the code
behavioral_analysis_capacity_exceeded and reason groups, bytes or findings.
The MVP limits are 1,000 distinct matching identities, 8 MiB of serialized identity
metadata and 5,000 findings per pass. Identity metadata includes operation key,
direction, protocol, status, route, method, payload location and event type.
Structural and behavioral states are independent. Check both lastSuccessAt
values before interpreting a lack of new findings as evidence of stability.
Errors
| Status | Body | Meaning |
|---|---|---|
400 | {"error":"invalid_environment_filter"} | environmentId is malformed |
401 | {"error":"unauthenticated"} | The workspace API key is missing or invalid |
403 | {"error":"insufficient_scope"} | The key does not carry integrations:read |
409 | {"error":"result_limit_exceeded"} | More than 100 matching Integrations would be returned |
Mode-scoped operational reads
Code example
GET /v1/incidentsGET /v1/incidents/{incidentId}GET /v1/repair-proposals/{proposalId}All three endpoints require a current workspace API key and an explicit
mode=sandbox or mode=live. Incident reads require incidents:read; proposal
reads require repairs:read. A workspace owner issues these explicit scopes;
existing keys keep their original permissions. An ingest token, setup token,
browser cookie, or an observation-only key cannot authenticate these reads.
Code example
curl 'https://api.seamward.com/v1/incidents?mode=sandbox&status=open&limit=25' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"| Query | Required | Values and behavior |
|---|---|---|
mode | Yes | sandbox or live; there is no implicit default. |
status | List only, optional | open or resolved; omit to read both. |
limit | List only, optional | 1 to 100; defaults to 25. |
cursor | List only, optional | Use the returned opaque cursor with the original mode and status filter. |
The incident list returns mode, items, and nextCursor. Ordering is newest
creation time first, then ascending ID. A null cursor means the page has no
continuation. An empty result is a successful empty page. A cursor from a
foreign workspace, mode, or status filter is refused.
Code example
{ "mode": "sandbox", "items": [], "nextCursor": null}Read one incident using its ID from the list:
Code example
curl 'https://api.seamward.com/v1/incidents/inc_example?mode=sandbox' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"incident contains its connection ID, mode and environment, kind, status,
summary, affected record count, resolution state, first/last observation times,
creation/update times, and nullable resolution time. Detail also includes up to
100 retained relational observationIds and finding references (id, kind,
path, and summary). evidenceTruncated marks omitted references. This is a
bounded evidence preview; it does not return raw evidence JSON or historical
references that have expired from the relational evidence store.
Read proposal provenance with its original mode:
Code example
curl 'https://api.seamward.com/v1/repair-proposals/rep_example?mode=sandbox' \ -H "Authorization: Bearer $SEAMWARD_API_KEY"Code example
{ "proposal": { "id": "rep_example", "incidentId": "inc_example", "connectionId": "int_example", "mode": "sandbox", "environmentId": "env_sandbox", "status": "queued", "createdAt": "2026-09-29T06:00:00.000Z", "updatedAt": "2026-09-29T06:00:00.000Z", "errorCode": null, "validation": null, "decision": null }}A recorded validation contains its ID, replay run ID, validity, replay result, and creation time. A recorded decision contains its ID, approved/rejected outcome, actor type, proposal fingerprint, validation report ID, and creation time. Candidate code, raw evidence, execution tokens, leases, and actor email addresses are omitted. A provenance read cannot approve a repair or prove that it was deployed. Review candidate artifacts and approval details in the console.
All responses use Cache-Control: no-store. A selected-mode record with a
foreign or wrong-mode ID is indistinguishable from a missing record. Reads
recheck current key authority within the transaction, including expiry before
returning the result.
| Status | Error | Recovery |
|---|---|---|
| 400 | invalid_incident_query | Supply the explicit mode and valid list fields. Unknown fields are refused. |
| 400 | invalid_evidence_query | Supply only the required mode for a detail read. |
| 400 | invalid_incident_cursor | Restart the list with its original workspace, mode and filter. |
| 401 | unauthenticated | Use a current workspace key for an active workspace. |
| 403 | insufficient_scope | Obtain the explicit incident or repair read permission from a workspace owner. |
| 404 | incident_not_found or repair_proposal_not_found | Check the original workspace, mode, and ID. |
| 409 | workspace_unavailable or workspace_modes_unavailable | Restore access or complete the reviewed workspace mode conversion. |
Planned endpoints
Public incident resolution and repair approval APIs are planned, not available. Use the console for those mutations. These operational reads do not grant permission to approve, deliver, or deploy a repair.
Authentication model
- Workspace-scoped API keys are created by an owner, shown once, stored only as a hash, and expire within one year.
- Integration, observation, incident, repair, and contract scopes separate inventory, evidence reads, proposal provenance, draft registration, and activation.
- Bearer authentication uses
Authorization: Bearer sw_api_...; contract requests do not use HMAC signing.
Repair approval and delivery remain explicit console decisions and are not exposed as write endpoints.
Next steps
- Ingest observations: the endpoint that is available today.
- Observation API: list evidence and read usage.
- Contract API: the available workspace automation surface.
- MCP overview: programmatic read access that works now, through OAuth.
Delete one connection
Connection-only deletion is available for canonical Sandbox/Live workspaces. It permanently removes the selected connection and its owned operational data. The shared Integration remains, including when you remove its final connection. Other connections, accepted usage totals, audit history, and canonical creation, setup, credential, and deletion receipts remain. Completed legacy credential and setup receipts also remain, including their original request, result and item lineage. Pending setup reviews that reference the removed connection expire; active OAuth bindings lose that connection reference.
An ingest token cannot perform this operation. Use a workspace API key with integrations:manage in Authorization: Bearer <key>. Keep the same key for the review, apply, status, and retries. An inactive workspace is unauthenticated. A legacy workspace returns workspace_modes_unavailable; its owner must complete the reviewed environment migration first.
Preview the exact mode
POST /v1/connections/{connectionId}/deletion-preview
Use the int_ connection ID from the Integration inventory, not its shared wint_ identity. The body is the empty JSON object {}. Mode overrides and unknown options are rejected.
Code example
curl -X POST 'https://api.seamward.com/v1/connections/int_sandbox_example/deletion-preview' \ -H "Authorization: Bearer $SEAMWARD_WORKSPACE_API_KEY" \ -H 'Content-Type: application/json' \ --data '{}'Replace the connection ID and set SEAMWARD_WORKSPACE_API_KEY to your workspace key. A 201 response describes the permanent impact:
Code example
{ "operationId": "conndel_example", "approvalFingerprint": "sha256:8ef4c6194a5cff12e4df19d13bb26b352bc36d3097a8a4fd086e4d6047e60f7c", "confirmationChallenge": "Candidate webhook (Sandbox)", "expiresAt": "2026-09-28T12:10:00.000Z", "connection": { "id": "int_sandbox_example", "workspaceIntegrationId": "wint_example", "environmentId": "env_sandbox", "mode": "sandbox", "name": "Candidate webhook", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook" }, "revisions": { "identity": "1", "configuration": "2", "impact": "3" }, "counts": { "approvalRecords": 0, "contractActivations": 1, "contracts": 1, "credentialOperations": 1, "expectedOutcomes": 1, "findings": 3, "incidents": 2, "observations": 15, "oauthBindings": 1, "repairArtifacts": 0, "repairDeliveries": 0, "repairProposals": 0, "repositoryMappings": 0, "replayDatasets": 0, "replayRuns": 0, "setupProvisioningItems": 1, "validationReports": 0, "webhookDeliveries": 0, "contractOperations": 1, "shapeSummaries": 2, "observationFindings": 3, "incidentObservations": 2 }, "hazards": { "backgroundJobs": 0, "activeReplayRuns": 0, "activeRepairProposals": 0, "activeDeliveries": 0, "crossConnectionReferences": 0 }, "preservedConnectionIds": ["int_live_example"]}| Field | Meaning |
|---|---|
operationId | Server-issued conndel_ review identifier. Retain it for apply and status. |
connection | Exact connection ID, shared Integration ID, Sandbox or Live mode, canonical environment ID, name, provider, direction, and protocol. |
revisions | Server-owned identity, configuration, and destructive-impact revisions. Review changes require a fresh preview. |
counts | Records removed or bindings scrubbed: contracts, contract operations, activations, observations, shape summaries, observation-finding links, incident-observation links, findings, incidents, expected outcomes, replay datasets and runs, repair proposals and artifacts, deliveries, approval records, validation reports, webhook receipts, repository mappings, and OAuth bindings. credentialOperations and setupProvisioningItems count retained historical references. Their completed receipts are preserved; they are not removal counts. |
hazards | Pending or claimed background jobs, active replay runs, active repair proposals, queued external deliveries, and references shared with another connection. Any nonzero value blocks apply. |
preservedConnectionIds | Other connections present during review. Their operational data and credentials are preserved. |
confirmationChallenge | Exact case-sensitive name and mode the reviewer must confirm. |
approvalFingerprint | Server-issued binding to this immutable review. Submit it unchanged. |
expiresAt | Ten minutes after preview creation. At expiry, apply is refused. |
Preview creation is limited to 30 per workspace per minute. 429 rate_limited includes Retry-After: 60. Responses are private and not cacheable. A preview makes no deletion and does not cancel work.
Apply the reviewed deletion
POST /v1/connection-deletions/{operationId}/apply
After reviewing the exact mode, counts, and preservation guarantees, submit the returned fingerprint and confirmation challenge. This permanently removes data and has no undo operation. There is no force option.
| Request | Required constraint |
|---|---|
operationId path parameter | The original server-issued conndel_ identifier. |
Idempotency-Key header | 8 to 128 printable non-space ASCII characters. Retain the original value for retries. |
approvalFingerprint body field | Exact sha256: fingerprint followed by 64 lowercase hexadecimal characters from the preview. |
confirmationName body field | Exact returned challenge, including (Sandbox) or (Live), 1 to 160 characters. |
Code example
curl -X POST 'https://api.seamward.com/v1/connection-deletions/conndel_example/apply' \ -H "Authorization: Bearer $SEAMWARD_WORKSPACE_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: remove-sandbox-20260929-01' \ --data '{"approvalFingerprint":"sha256:8ef4c6194a5cff12e4df19d13bb26b352bc36d3097a8a4fd086e4d6047e60f7c","confirmationName":"Candidate webhook (Sandbox)"}'Replace all review values with your response. The first completion returns 201 with replayed: false. The exact original-key retry returns 200 with replayed: true. The key shares a workspace-wide namespace with canonical creation and credential operations; reuse for a different request or action is refused.
Authorization is checked again in the deletion transaction. Changes to authorization, identity, configuration, or owned operational data invalidate a review, including changes later restored to their earlier values. A serialization conflict is retried internally at most twice with fresh authorization and a fresh snapshot; persistent contention returns deletion_preview_stale. Deletion, retained receipt, and audit commit together. No external GitHub issue or pull request is deleted.
Recover a lost response
GET /v1/connection-deletions/{operationId}
Code example
curl 'https://api.seamward.com/v1/connection-deletions/conndel_example' \ -H "Authorization: Bearer $SEAMWARD_WORKSPACE_API_KEY"Status returns 200. Before apply, it contains the preview plus status: "previewed"; after ten minutes, status: "expired". After completion, it returns the retained historical receipt even though the connection no longer exists:
Code example
{ "operationId": "conndel_example", "status": "completed", "connectionId": "int_sandbox_example", "workspaceIntegrationId": "wint_example", "mode": "sandbox", "name": "Candidate webhook", "counts": { "approvalRecords": 0, "contractActivations": 1, "contracts": 1, "credentialOperations": 1, "expectedOutcomes": 1, "findings": 3, "incidents": 2, "observations": 15, "oauthBindings": 1, "repairArtifacts": 0, "repairDeliveries": 0, "repairProposals": 0, "repositoryMappings": 0, "replayDatasets": 0, "replayRuns": 0, "setupProvisioningItems": 1, "validationReports": 0, "webhookDeliveries": 0, "contractOperations": 1, "shapeSummaries": 2, "observationFindings": 3, "incidentObservations": 2 }, "preservedConnectionIds": ["int_live_example"], "replayed": true}A receipt does not describe a subsequently recreated connection with the same ID. Replaying it cannot remove the replacement. Status and retries remain restricted to the original active key; deleting or revoking that key prevents recovery through this endpoint. No token or token hash is returned.
| Status | Error | Recovery |
|---|---|---|
| 400 | invalid_connection_deletion | Submit the strict empty preview body or the two apply fields. |
| 400 | idempotency_key_required | Supply a valid original key for apply. |
| 401 | unauthenticated | Use the original active workspace key and active workspace. |
| 403 | insufficient_scope | Obtain current integrations:manage permission. |
| 404 | connection_not_found or operation_not_found | Check the workspace, exact connection, operation ID, and original key. Other tenants and keys are not disclosed. |
| 409 | workspace_unavailable or workspace_modes_unavailable | Restore workspace availability or complete the reviewed environment migration. |
| 409 | deletion_preview_expired or deletion_preview_stale | Create a new preview and review its current impact. |
| 409 | confirmation_mismatch | Use the exact challenge from the reviewed preview. |
| 409 | idempotency_conflict | For recovery, resend the exact original request and key. For a separate operation, review it and use a new key. |
| 409 | connection_work_in_progress | Let background work and external delivery finish, then preview again. Do not remove delivery evidence to bypass this check. |
| 409 | connection_references_in_use | Resolve the cross-connection reference with its owner, then preview again. |
| 429 | rate_limited | Wait 60 seconds before another preview. |
Whole-Integration compatibility
The CLI integrations delete command and setup MCP delete_integration tool delegate to the canonical whole-Integration service. They refuse deletion if any configured connection falls outside the selected one-mode setup grant. A Sandbox grant cannot remove Live. Use the workspace-key whole deletion API when both modes are configured. Neither command provides connection-only deletion.
Canonical browser connection detachment uses the same immutable service. Previews created by the historical detachment service cannot apply after a workspace enters canonical mode; create a fresh preview. Historical legacy records remain under their original contract and are not converted into canonical receipts.
For safe setup replacement and permanent-removal steps, see Automatic setup. If apply is refused, follow Deletion troubleshooting.
Legacy setup deletion retains its whole-Integration meaning through the canonical service. It requires every configured connection to be in the current client’s exact one-mode grant. A workflow configured in both modes requires the workspace-key API below.
Delete a whole Integration
Whole Integration deletion is available for canonical Sandbox and Live workspaces. It permanently removes the shared workflow and every configured connection. An empty workflow can also be removed. Use connection deletion when you intend to remove only one mode.
All three endpoints require a workspace API key with integrations:manage. This is a destructive operation with no undo. Accepted usage, audit history and immutable operation receipts survive. External GitHub issues and pull requests are not deleted.
Review both connections
POST /v1/integrations/{workspaceIntegrationId}/deletion-preview
Pass the shared wint_ ID and an empty JSON object. The response describes the shared identity revision and each configured connection's mode, revision, counts and hazards. Zero, one or two connections can appear. Both modes are covered by the whole Integration operation. The oauthBindings count includes setup bindings and remote MCP grants affected by each removal. Removing one selected connection invalidates the entire remote grant, including its remaining selections. A changed grant requires a fresh deletion review. Reauthorize the surviving connections after deletion.
Code example
curl -X POST 'https://api.seamward.com/v1/integrations/wint_example/deletion-preview' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ --data '{}'Example 201 response:
Code example
{ "operationId": "wintdel_example", "approvalFingerprint": "sha256:8ef4c6194a5cff12e4df19d13bb26b352bc36d3097a8a4fd086e4d6047e60f7c", "expiresAt": "2026-09-28T12:10:00.000Z", "integration": { "id": "wint_example", "name": "Candidate webhook", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook", "revision": "1" }, "confirmationChallenge": "Candidate webhook (all connections)", "connections": [ { "connection": { "id": "int_sandbox_example", "workspaceIntegrationId": "wint_example", "environmentId": "env_sandbox", "mode": "sandbox", "name": "Candidate webhook", "provider": "ATS", "direction": "inbound", "protocol": "http-webhook" }, "revisions": { "identity": "1", "configuration": "2", "impact": "3" }, "confirmationChallenge": "Candidate webhook (Sandbox)", "counts": { "approvalRecords": 0, "contractActivations": 1, "contracts": 1, "credentialOperations": 1, "expectedOutcomes": 1, "findings": 3, "incidents": 2, "observations": 15, "oauthBindings": 1, "repairArtifacts": 0, "repairDeliveries": 0, "repairProposals": 0, "repositoryMappings": 0, "replayDatasets": 0, "replayRuns": 0, "setupProvisioningItems": 1, "validationReports": 0, "webhookDeliveries": 0, "contractOperations": 1, "shapeSummaries": 2, "observationFindings": 3, "incidentObservations": 2 }, "hazards": { "backgroundJobs": 0, "activeReplayRuns": 0, "activeRepairProposals": 0, "activeDeliveries": 0, "crossConnectionReferences": 0 }, "preservedConnectionIds": [] } ]}Every configured connection will be removed. preservedConnectionIds is empty in this whole Integration review. The review expires after 10 minutes. Shared with connection deletion, preview creation is limited to 30 per workspace per minute; 429 rate_limited includes Retry-After: 60.
Apply exactly that review
POST /v1/integration-deletions/{operationId}/apply
Use the wintdel_ operation ID, exact approval fingerprint and the complete confirmation challenge, including (all connections). Preserve an Idempotency-Key of 8 to 128 printable non-space ASCII characters. The body has only these two fields:
Code example
{ "approvalFingerprint": "sha256:8ef4c6194a5cff12e4df19d13bb26b352bc36d3097a8a4fd086e4d6047e60f7c", "confirmationName": "Candidate webhook (all connections)"}Code example
curl -X POST 'https://api.seamward.com/v1/integration-deletions/wintdel_example/apply' \ -H "Authorization: Bearer $SEAMWARD_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: delete-candidate-workflow-001' \ --data '{"approvalFingerprint":"sha256:8ef4c6194a5cff12e4df19d13bb26b352bc36d3097a8a4fd086e4d6047e60f7c","confirmationName":"Candidate webhook (all connections)"}'201 confirms atomic completion. An exact original-key retry returns 200 with replayed: true:
Code example
{ "operationId": "wintdel_example", "status": "completed", "workspaceIntegrationId": "wint_example", "name": "Candidate webhook", "connections": [ { "connectionId": "int_sandbox_example", "mode": "sandbox", "counts": { "approvalRecords": 0, "contractActivations": 1, "contracts": 1, "credentialOperations": 1, "expectedOutcomes": 1, "findings": 3, "incidents": 2, "observations": 15, "oauthBindings": 1, "repairArtifacts": 0, "repairDeliveries": 0, "repairProposals": 0, "repositoryMappings": 0, "replayDatasets": 0, "replayRuns": 0, "setupProvisioningItems": 1, "validationReports": 0, "webhookDeliveries": 0, "contractOperations": 1, "shapeSummaries": 2, "observationFindings": 3, "incidentObservations": 2 } } ], "replayed": false}The server checks authorization, the shared identity revision, every connection revision, data impact and hazards before deleting any record. An active replay, repair, delivery or queued background job returns connection_work_in_progress. Cross-connection evidence references return connection_references_in_use. Both failures preserve every connection. Changed authorization, configuration or impact returns deletion_preview_stale; create a new review after resolving the change.
Recover a lost response
GET /v1/integration-deletions/{operationId}
Use the original credential to read previewed, expired or completed status. After completion, the immutable receipt is returned with replayed: true without looking up the deleted identity. A different credential cannot claim the operation. Retry apply only with its original body and request key.
A current owner or administrator who originally approved the browser operation can read its token-free receipt at GET /workspaces/{workspaceSlug}/integration-deletions/{operationId}, including an archived workspace. This browser session route does not accept workspace API keys.
Resolve a refused request
| Status | Error | Recovery |
|---|---|---|
| 400 | invalid_integration_deletion | Use an empty preview body or exactly the two apply fields. |
| 400 | idempotency_key_required | Supply the original valid request key. |
| 401 | unauthenticated | Use a current workspace API key. |
| 403 | insufficient_scope | Obtain integrations:manage for this workspace. |
| 404 | integration_not_found or operation_not_found | Check the shared ID, original actor and workspace. Foreign IDs are not disclosed. |
| 409 | workspace_modes_unavailable or workspace_unavailable | Resolve workspace lifecycle or canonical mode availability before creating another review. |
| 409 | confirmation_mismatch | Submit the exact server-issued challenge. |
| 409 | deletion_preview_stale or deletion_preview_expired | Create and review a new preview. |
| 409 | idempotency_conflict | Reuse the original body and credential for a completed operation. Use a new key for a separate operation. |
| 409 | connection_work_in_progress or connection_references_in_use | Resolve the reviewed hazards; then review the complete Integration again. |
| 429 | rate_limited | Wait for Retry-After. |
| 503 | mode_cutover_write_paused | Retry the same request and key after Retry-After. |
Read account mode usage
GET /v1/accounts/{accountId}/usage returns pooled accepted observations for the
current UTC calendar month. Use an account API key carrying account:usage:read.
Workspace keys, setup tokens, and browser cookies cannot authorize this read.
Obtain the account ID and credential through the verified account management
requests below. There are no query parameters or request body.
Quota enforcement is scoped to Sandbox. enforcement.scope is always
sandbox; status and startsAt describe that Sandbox policy. Live counts and
remaining plan allowance are informational. Activating this Sandbox policy does
not introduce Live rejection or overage charges.
Code example
curl -sS "https://api.seamward.com/v1/accounts/$SEAMWARD_ACCOUNT_ID/usage" \ -H "Authorization: Bearer $SEAMWARD_ACCOUNT_API_KEY"Code example
{ "accountId": "ba_example", "period": "utc_calendar_month", "periodStart": "2026-09-01T00:00:00.000Z", "periodEnd": "2026-10-01T00:00:00.000Z", "enforcement": { "scope": "sandbox", "status": "off", "publishedAt": null, "cutoverAt": null, "startsAt": null }, "sandbox": { "recordedCount": 3, "monthlyLimit": 10000, "remainingCount": 9997, "retentionDays": 7, "retentionCutoverAt": null, "work": { "enforcement": "active", "repairValidations": { "monthlyLimit": 3, "reservedCount": 0, "recordedCount": 0, "remainingCount": 3 }, "aiInvestigations": { "monthlyLimit": 1, "recordedCount": 0, "remainingCount": 1 }, "activeExecutions": 0, "concurrentLimit": 1, "submittedObservationsPerMinute": 1000, "ingestRequestsPerMinute": 100 } }, "live": { "recordedCount": 7, "monthlyLimit": 50000, "remainingCount": 49993, "unclassifiedCount": 2 }}| Field | Meaning |
|---|---|
periodStart, periodEnd | Inclusive start and exclusive end of one UTC calendar month. |
sandbox.recordedCount | Accepted Sandbox observations across the account's workspaces. |
live.recordedCount | Accepted Live observations plus historical usage whose mode cannot be established. |
live.unclassifiedCount | The historical portion already included in Live, never an extra charge. |
monthlyLimit, remainingCount | Each mode's nonnegative remaining allowance. Sandbox defaults to 10,000. Live plan remaining is informational. |
enforcement.scope | Always sandbox. This schedule cannot activate Live rejection. |
enforcement.status | off before scheduling, grace before its effective date, or active once Sandbox admission checks apply. |
publishedAt, cutoverAt, startsAt | Policy publication, reviewed cutover, and enforcement dates, or null. |
sandbox.retentionDays, retentionCutoverAt | Prospective retention duration and eligibility date. A null date means this new policy has not begun. |
Moving or removing a workspace, connection, or retained observation does not remove charges already attributed to its admission account. No workspace names, identifiers, raw observations, or credential material appear in this response. The response is never cached.
| Status | Error | Recovery |
|---|---|---|
400 | invalid_account_usage_query | Remove all query fields. |
401 | unauthenticated | Use a current account key. Its creator must still have a verified email and account owner or billing administrator access, and the account must be active. |
404 | account_not_found | Use the exact account bound to the credential. Foreign accounts are indistinguishable from missing accounts. |
409 | account_access_changed | Recheck access and retry the read with current authorization. |
503 | usage_unavailable | Retry later or contact support. Do not treat missing usage as zero. |
Sandbox work usage
sandbox.work reports active resource safeguards independently of observation
quota scheduling. Repair validations are reserved on admission and charged once
when execution starts. reservedCount plus recordedCount consumes the monthly
allowance. Never-started cancellation releases its reservation; failed validation
counts. AI dispatch is counted before the provider is called, including uncertain
responses. Recovery does not repeat an uncertain call. activeExecutions covers
the whole account, including prior-month work, and is at most one.
Manage account usage keys
Account owners and billing administrators use a verified browser session for
these requests. List accessible accounts with GET /billing-accounts. Obtain the
same mode usage response with GET /billing-accounts/{accountId}/mode-usage,
including when the account has no active workspace. Key creation and revocation
also require an Origin header matching the console origin. These management
routes do not accept workspace keys, setup tokens, or account usage keys.
Code example
POST /billing-accounts/{accountId}/api-keysOrigin: https://seamward.comContent-Type: application/json
{ "name": "Account usage reporting", "scopes": ["account:usage:read"], "expiresAt": "2027-01-01T00:00:00.000Z"}The 201 response contains apiKey metadata and secret. The secret has the
sw_acct_ prefix and 43 URL-safe characters; it appears once and is stored only
as a SHA-256 hash. Metadata contains id, accountId, name, tokenPrefix,
scopes, createdAt, expiresAt, lastUsedAt, and revokedAt. Dates are UTC
ISO strings; the last two may be null. Save the secret directly to your secret
store. If creation succeeded but its response was lost, list metadata, revoke
the orphaned key, and issue a replacement. Creation does not replay a secret.
The name must contain 1 to 80 characters after trimming. The sole scope is
account:usage:read. Expiry must be in the future and within 365 days. Extra
body fields are rejected. There may be at most 50 unexpired, unrevoked keys per
account. Creation is limited to 10 successful requests per actor and account
per hour; 429 rate_limited carries Retry-After: 3600.
GET /billing-accounts/{accountId}/api-keys returns { "apiKeys": [], "nextCursor": null } when empty. limit defaults to 25 and accepts 1 to 100.
Pass the returned opaque cursor to continue; it is bound to the account.
Keys are ordered by descending creation time and then ID. Lists include
expired and revoked keys, without secrets or hashes.
POST /billing-accounts/{accountId}/api-keys/{apiKeyId}/revoke accepts exactly
{} and returns 200 with { "apiKey": <metadata> }. Repeating revocation is
safe and does not add another audit event. Revoking a key stops future usage
reads. Scopes and expiry are immutable: issue and verify a replacement before
revoking a working key.
All routes check fresh account access, independent of workspace membership.
401 unauthenticated requires signing in. 403 email_verification_required
requires email verification; 403 untrusted_origin requires the correct
console origin. 404 account_not_found or account_api_key_not_found conceals
foreign targets. Invalid create/revoke bodies return 400 invalid_account_api_key;
invalid list filters or cursors return 400 invalid_account_key_query or
invalid_account_key_cursor. 409 account_key_limit_reached requires revoking
unused keys; 409 account_access_changed requires a fresh authorization check.
Account audit records never contain secret material.
See monthly admission behavior before implementing delivery retries.
Historical session receipt access
Canonical browser credential controls use reviewed operations and show new tokens once. Reloading or reading a receipt never recovers a plaintext token. The following session reads use the original user's current workspace membership, independent of which workspace is active in the browser:
| Receipt | Session endpoint |
|---|---|
| Creation | GET /workspaces/{workspaceSlug}/integration-operations/{operationId} |
| Credential change | GET /workspaces/{workspaceSlug}/credential-operations/{operationId} |
| Completed mode setup | GET /workspaces/{workspaceSlug}/connection-setup/{operationId} |
| Completed connection removal | GET /workspaces/{workspaceSlug}/connection-deletions/{operationId} |
| Completed configuration copy or compensation | GET /workspaces/{workspaceSlug}/configuration-operations/{operationId} |
| Completed rule mutation | GET /workspaces/{workspaceSlug}/rule-operations/{operationId} |
Only the original actor who remains an owner or admin can read these completed,
token-free receipts in an archived workspace. Another owner cannot inherit the
receipt. A current member without owner/admin access receives 404 at the
session boundary. Pending previews and all mutations remain unavailable while
archived. A historical credential receipt returns historical:true; completed
setup or creation returns its retained replay shape with
credentialRecoveryRequired:true. No receipt asserts current connection health.
This exception grants no archived access to workspace API keys. Keys require an
active workspace, so archive generally returns 401 at public authentication.
If archive or rebinding happens after authorization but before the transaction,
the service returns 409 workspace_unavailable. Restore the workspace before
reviewing new operations. Repeating a mutation is not a historical receipt read.
