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 pathResult
GET /workspacesLists 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 /workspacesCreates 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-accountsLists accounts the user owns or administers, with the active workspace count.
GET /billing-accounts/{accountId}/usageReturns the account's UTC calendar-month observation total, limit, remaining count, and per-workspace contributions.
POST /workspaces/{workspaceSlug}/archiveArchives a workspace owned by the account. New ingestion and customer writes stop.
POST /workspaces/{workspaceSlug}/restoreRestores 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.

OperationEndpoint
Current statusGET /v1/connections/{connectionId}/credentials
Issue a tokenPOST /v1/connections/{connectionId}/credentials/issue
Rotate a tokenPOST /v1/connections/{connectionId}/credentials/rotate
Revoke a tokenPOST /v1/connections/{connectionId}/credentials/revoke
Verify credentialsPOST /v1/connections/{connectionId}/credentials/verify
Recover a receiptGET /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.

StatusErrorRecovery
400invalid_credential_requestCorrect the body. Unknown fields and caller-supplied tenant or mode are rejected.
400idempotency_key_requiredRetain a valid key for the mutation and its identical retries.
401unauthenticatedAuthorize with a current workspace key for an active workspace.
403insufficient_scopeUse the original key with current integrations:manage authorization. A key revoked or expired before or during the transaction also returns this error.
404connection_not_foundRefresh inventory. Foreign workspace IDs are also undisclosed.
404operation_not_foundUse the original key and operation ID. Other keys cannot recover the receipt.
409workspace_unavailableRestore the workspace or resolve its organization binding before a new operation.
409workspace_modes_unavailableResolve canonical migration before using these endpoints.
409connection_configuration_changedConfiguration or authority changed. No token change commits. Read and review current state before creating a new operation.
409credential_already_issuedReview rotation explicitly rather than issuing over an active credential.
409credential_not_issuedIssue a credential before attempting rotation.
409credential_verification_failedCheck the exact Connection key and current private token.
409idempotency_conflictRestore the original action, body, and authorization, or deliberately start a new reviewed operation.

Create an Integration and first connection

Code example

POST /v1/integrations

Create 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"}'
FieldRequiredMeaning
modeYessandbox or live; there is no default or legacy alias.
nameYesWorkflow name, trimmed to 1 to 120 characters.
providerYesProvider identity, trimmed to 1 to 120 characters.
directionYesinbound or outbound.
protocolYeshttp-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.

StatusCodeRecovery
400invalid_integrationCorrect the body and use a canonical mode.
400idempotency_key_requiredSupply 8 to 128 printable non-space ASCII characters.
401unauthenticatedAuthorize with a valid, unexpired workspace API key.
403insufficient_scopeIssue a key with integrations:manage; retry only with the original binding.
409workspace_authorization_changedRefresh and review current permissions before a new creation attempt.
409workspace_modes_unavailableAsk the workspace operator to complete migration or repair the canonical pair.
409workspace_unavailableRestore or reauthorize the workspace before creating a connection.
409idempotency_conflictRestore 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/preview

For 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}/apply

After 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.

StatusCodeRecovery
400invalid_connection_setupCorrect the request fields or approval fingerprint format.
400configuration_scope_mismatchSelect the same workflow’s other canonical mode connection.
400configuration_selection_invalidChoose unique declared contract and rule IDs from the source.
400idempotency_key_requiredSupply 8 to 128 printable non-space ASCII characters for apply.
401unauthenticatedAuthorize with an active workspace API key.
403insufficient_scopeUse the original key with current management permission.
404integration_not_found, operation_not_foundCheck the exact shared ID, workspace, and original key.
409workspace_modes_unavailable, workspace_unavailableComplete migration or restore workspace availability.
409configuration_snapshot_too_largeReduce the selected configuration to fit within 1 MiB.
409connection_already_configuredUse a reviewed configuration copy for the existing connection.
409approval_mismatchRestore the exact fingerprint returned for this operation.
409connection_preview_expired, connection_preview_staleRequest and review a fresh preview.
409idempotency_conflictRetry 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/preview

Code 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}
FieldMeaning
operationId, actionExact copy or compensation operation identity.
fingerprint, expiresAtApproval value and server-issued ten-minute deadline.
snapshot.identityShared Integration identity and monotonic revision.
snapshot.source, snapshot.destinationExplicit connection IDs, mode and reviewed revisions.
snapshot.contracts, snapshot.rulesExact permitted drafts and disabled definitions.
originalOperationId, copiedArtifactsNull 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-preview

Send 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.

StatusCodeRecovery
400invalid_configuration_request, configuration_selection_invalid, configuration_scope_mismatchCorrect exact IDs, unique selections and the opposite mode of the same shared Integration.
400idempotency_key_requiredProvide a retained apply key in the documented format.
401, 403unauthenticated, insufficient_scopeRestore the original key's current management authority.
404connection_not_found, integration_not_found, operation_not_foundCheck exact workspace, target and original actor binding.
409configuration_destination_conflictResolve duplicate destination definitions, then review again.
409configuration_snapshot_too_largeReduce selected document content or the selection.
409configuration_preview_stale, configuration_preview_expired, approval_mismatchRead current state and create a fresh review.
409configuration_compensation_unavailableKeep used configuration; review a separate explicit change instead.
409idempotency_conflictRecover the original operation or use a new key for a new review.
409workspace_unavailable, workspace_modes_unavailableRestore workspace availability or complete canonical mode migration.
429rate_limitedWait 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}
FieldCreateUpdateDelete
expectedRevisionRequired reviewed decimal-string epochRequiredRequired
sourceEventTypeRequired, 1 to 120 letters, digits, ., _, :, -OptionalRejected
expectedObjectTypeSame format, requiredOptionalRejected
maxDelayMsRequired integer, 1,000 to 86,400,000OptionalRejected
enabledDefaults to falseOptional explicit booleanRejected

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.

StatusCodeRecovery
400invalid_rule_request, invalid_rule_cursorCorrect strict fields or restart pagination in the exact connection.
400idempotency_key_requiredSupply and retain a correctly formatted mutation key.
401, 403unauthenticated, insufficient_scopeUse the required current workspace authority.
404connection_not_found, expected_outcome_not_found, operation_not_foundCheck exact IDs, workspace and original actor.
409rule_cursor_stale, connection_configuration_changedRead current state and review again.
409expected_outcome_already_existsUse the existing definition or review an explicit update.
409expected_outcome_has_incident_historyPreserve history and review disabling the rule instead.
409idempotency_conflictRecover the original operation. Use a new key for a separately reviewed request.
409workspace_unavailable, workspace_modes_unavailableRestore workspace access or complete canonical mode migration.
429rate_limitedWait 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/environments

Discover 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    }  ]}
FieldTypeMeaning
modelcanonical or legacyCanonical workspaces have exactly Sandbox and Live. Existing workspaces retain their original environments until reviewed migration.
environmentsarray, 1 to 100 itemsExact stored environment records in this workspace.
idstring beginning env_Exact target identifier. Do not replace an identifier based on its display name or classification.
name, slugnonempty stringsDisplay name and navigation slug.
categorysandbox, live, development, production, or stagingStored environment category.
modesandbox or liveClassification for presentation. Development and Staging classify as Sandbox; Production classifies as Live.
isDefaultbooleanSandbox 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.

StatusBodyRecovery
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=50

Code 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

StatusBodyMeaning
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"
QueryRequiredValues and behavior
modeYessandbox or live; there is no implicit default.
statusList only, optionalopen or resolved; omit to read both.
limitList only, optional1 to 100; defaults to 25.
cursorList only, optionalUse 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.

StatusErrorRecovery
400invalid_incident_querySupply the explicit mode and valid list fields. Unknown fields are refused.
400invalid_evidence_querySupply only the required mode for a detail read.
400invalid_incident_cursorRestart the list with its original workspace, mode and filter.
401unauthenticatedUse a current workspace key for an active workspace.
403insufficient_scopeObtain the explicit incident or repair read permission from a workspace owner.
404incident_not_found or repair_proposal_not_foundCheck the original workspace, mode, and ID.
409workspace_unavailable or workspace_modes_unavailableRestore 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

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"]}
FieldMeaning
operationIdServer-issued conndel_ review identifier. Retain it for apply and status.
connectionExact connection ID, shared Integration ID, Sandbox or Live mode, canonical environment ID, name, provider, direction, and protocol.
revisionsServer-owned identity, configuration, and destructive-impact revisions. Review changes require a fresh preview.
countsRecords 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.
hazardsPending or claimed background jobs, active replay runs, active repair proposals, queued external deliveries, and references shared with another connection. Any nonzero value blocks apply.
preservedConnectionIdsOther connections present during review. Their operational data and credentials are preserved.
confirmationChallengeExact case-sensitive name and mode the reviewer must confirm.
approvalFingerprintServer-issued binding to this immutable review. Submit it unchanged.
expiresAtTen 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.

RequestRequired constraint
operationId path parameterThe original server-issued conndel_ identifier.
Idempotency-Key header8 to 128 printable non-space ASCII characters. Retain the original value for retries.
approvalFingerprint body fieldExact sha256: fingerprint followed by 64 lowercase hexadecimal characters from the preview.
confirmationName body fieldExact 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.

StatusErrorRecovery
400invalid_connection_deletionSubmit the strict empty preview body or the two apply fields.
400idempotency_key_requiredSupply a valid original key for apply.
401unauthenticatedUse the original active workspace key and active workspace.
403insufficient_scopeObtain current integrations:manage permission.
404connection_not_found or operation_not_foundCheck the workspace, exact connection, operation ID, and original key. Other tenants and keys are not disclosed.
409workspace_unavailable or workspace_modes_unavailableRestore workspace availability or complete the reviewed environment migration.
409deletion_preview_expired or deletion_preview_staleCreate a new preview and review its current impact.
409confirmation_mismatchUse the exact challenge from the reviewed preview.
409idempotency_conflictFor recovery, resend the exact original request and key. For a separate operation, review it and use a new key.
409connection_work_in_progressLet background work and external delivery finish, then preview again. Do not remove delivery evidence to bypass this check.
409connection_references_in_useResolve the cross-connection reference with its owner, then preview again.
429rate_limitedWait 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

StatusErrorRecovery
400invalid_integration_deletionUse an empty preview body or exactly the two apply fields.
400idempotency_key_requiredSupply the original valid request key.
401unauthenticatedUse a current workspace API key.
403insufficient_scopeObtain integrations:manage for this workspace.
404integration_not_found or operation_not_foundCheck the shared ID, original actor and workspace. Foreign IDs are not disclosed.
409workspace_modes_unavailable or workspace_unavailableResolve workspace lifecycle or canonical mode availability before creating another review.
409confirmation_mismatchSubmit the exact server-issued challenge.
409deletion_preview_stale or deletion_preview_expiredCreate and review a new preview.
409idempotency_conflictReuse the original body and credential for a completed operation. Use a new key for a separate operation.
409connection_work_in_progress or connection_references_in_useResolve the reviewed hazards; then review the complete Integration again.
429rate_limitedWait for Retry-After.
503mode_cutover_write_pausedRetry 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  }}
FieldMeaning
periodStart, periodEndInclusive start and exclusive end of one UTC calendar month.
sandbox.recordedCountAccepted Sandbox observations across the account's workspaces.
live.recordedCountAccepted Live observations plus historical usage whose mode cannot be established.
live.unclassifiedCountThe historical portion already included in Live, never an extra charge.
monthlyLimit, remainingCountEach mode's nonnegative remaining allowance. Sandbox defaults to 10,000. Live plan remaining is informational.
enforcement.scopeAlways sandbox. This schedule cannot activate Live rejection.
enforcement.statusoff before scheduling, grace before its effective date, or active once Sandbox admission checks apply.
publishedAt, cutoverAt, startsAtPolicy publication, reviewed cutover, and enforcement dates, or null.
sandbox.retentionDays, retentionCutoverAtProspective 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.

StatusErrorRecovery
400invalid_account_usage_queryRemove all query fields.
401unauthenticatedUse 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.
404account_not_foundUse the exact account bound to the credential. Foreign accounts are indistinguishable from missing accounts.
409account_access_changedRecheck access and retry the read with current authorization.
503usage_unavailableRetry 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:

ReceiptSession endpoint
CreationGET /workspaces/{workspaceSlug}/integration-operations/{operationId}
Credential changeGET /workspaces/{workspaceSlug}/credential-operations/{operationId}
Completed mode setupGET /workspaces/{workspaceSlug}/connection-setup/{operationId}
Completed connection removalGET /workspaces/{workspaceSlug}/connection-deletions/{operationId}
Completed configuration copy or compensationGET /workspaces/{workspaceSlug}/configuration-operations/{operationId}
Completed rule mutationGET /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.