Register contracts

You can register contracts in the console, through the public API, or from a reviewed local discovery plan with assisted codebase setup. Every method creates an immutable draft that must be explicitly activated.

Register a declared contract when you want structural analysis to compare each observation with an explicit operation schema. Registration creates an immutable draft. Analysis changes only after an owner or admin activates that draft.

Before you begin

You need an integration with a direction and protocol, owner or admin access, and either an OpenAPI document or JSON Schema for one operation. Use representative route templates and event types, never concrete customer identifiers.

Choose the import

Use OpenAPI when one document contains several request, response, or webhook schemas. Use JSON Schema when you need to attach one schema to one method, route, event, payload location, and optional response status selector.

Seamward supports JSON and YAML in the console. The public API accepts JSON request bodies. OpenAPI import currently supports GET, POST, PUT, PATCH, and DELETE, JSON media types, local references, and the documented JSON Schema subset. Review the exact import boundaries before relying on composition or remote references.

Draft from traffic

If the Integration is already receiving traffic, you do not have to write the document. Open Contracts and select Draft from traffic. Seamward builds a draft from the payload shapes it has observed in the mode you are in and shows you what it rests on before anything is saved:

  • each operation it saw, with the number of payloads and the dates they cover
  • each field with its type, how often it appeared, and whether it is drafted required or optional
  • when a version is active, each difference from it, marked Added, Loosened, Tightened or Retyped
  • a warning on any difference that matches a change Seamward recently detected, because accepting it makes the contract agree with that traffic
  • under Kept as they are, each operation of the active version that had no traffic, which the draft keeps unchanged

Choose a version label and select Create draft. The draft is registered like any other version: it appears in Test and Live and is active in neither until you activate it.

A draft can only say what was seen:

  • Seamward reads the shape of a payload, never its values, so a draft has field names and types. It has no enumerations and no formats.
  • A field is marked required only when every payload had it and at least 50 payloads were seen. With fewer, nothing is newly marked required, and a field the active version requires stays required while every payload still has it.
  • Inside an array, required means present in every kind of item seen.
  • Success and error responses are drafted separately.
  • When the draft is one version for every operation, an operation the active version describes that had no traffic in the window is kept exactly as it is. Silence says nothing about it, so it is neither changed nor dropped. A draft made one operation at a time cannot keep the others: activating it replaces the active version.
  • HTTP API operations, and webhook events that each have an event type, are drafted as one version. Queues, feeds and webhooks without an event type are drafted one operation at a time.

Review a draft as you would one you wrote. A field that happened to be present in every payload so far may still be optional.

Keep a contract current from the command line

seamward contracts sync drafts from traffic, shows you the same comparison, and asks before it changes anything:

Code example

$ seamward contracts sync --connection int_examplePaystack webhook (Test): 2,104 payloads in the last 7 daysActive version 1.0.0, proposed 1.1.0
POST /webhooks/paystack charge.success (message)  added      $.email
[y] publish  [d] save draft  [n] skip:
  • y registers the draft and activates it in the mode of that connection.
  • d registers the draft and leaves the active version as it is.
  • n, or anything else, changes nothing.

Outside a terminal there is nobody to ask, so choose what the command may do:

Code example

seamward contracts sync --connection int_example --check

--check changes nothing and exits with status 1 when the contract is out of date. Use it in a pipeline to fail a build until the contract has been reviewed.

Code example

seamward contracts sync --connection int_example --publish

--publish activates a draft only when every change adds to the contract or loosens it. It registers the draft and does not activate it when:

  • a change tightens the contract or changes a type,
  • a change matches something Seamward recently detected, because accepting it would stop that detection, or
  • the draft holds one operation and activating it would replace a version that checks another.

In each case the command says why, and the draft waits for your review in the console. Activation states the version the draft was compared with, so it is refused if someone activated another version in the meantime.

Add --window-days 30 to draft from a longer period and --declared-version 2026.10 to choose the label yourself. seamward contracts draft --connection int_example --out contract-request.json writes the draft as a request file for seamward contracts register without saving anything.

Register a draft

  1. Open Integrations, select the integration, and open Contracts.
  2. Select Register contract or Register new version.
  3. Enter a unique declared version.
  4. Choose OpenAPI or JSON Schema for one operation, then paste the document.
  5. For JSON Schema, complete the stable operation selector.
  6. Submit the form. The new card appears as Draft and existing analysis continues using the active version.

You register a version once. The same draft appears in both Test and Live, and you activate it in each mode separately, so you can try a version in Test before it can raise an incident in Live.

An identical retry returns the existing immutable version, which makes recovery from a lost response safe. If registration returns contract_version_already_exists, the same declared version already has different document content or operation selectors. Choose a new immutable version label; do not overwrite the existing version. A version label means one thing across both modes, so this also applies when the other mode already holds that label with different content.

Review and activate

Open each operation and inspect its method, route template, event type, payload location, status selector, and schema. When the version is correct, choose Activate version. A previous immutable version offers Roll back to this version.

Activation applies to the mode you are in and leaves the other mode's active version unchanged. It records a revision and audit event, supersedes the previous active version in that mode, and queues reanalysis in one transaction. If another deployment changed the active version first, refresh and review the new state before retrying.

Automate from CI

Create a workspace API key with contracts:write and contracts:activate, store the one-time sw_api_... secret in CI, then call:

Code example

POST /v1/integrations/{integrationId}/contractsPOST /v1/integrations/{integrationId}/contracts/{contractVersionId}/activate

The registration call creates a draft. The activation body must include the active version CI reviewed as expectedActiveContractVersionId, including null for the first activation. A stale precondition returns 409 instead of replacing another pipeline's version.

Include expectedScope with the Integration direction and protocol in every new registration request. The API rejects a mismatch before storing the draft. This guard is optional only for backward compatibility with earlier API clients; the Seamward CLI and console always send it.

See the Contract API reference for complete request bodies, scopes, responses, and errors.

Watch the provider's published contract

You set the address once: it is watched for both Test and Live, and changing or removing it applies to both.

A declared contract says what you expect. A provider's own published document says what they intend, often before the traffic changes. Seamward can watch that document and raise an advisory when a new version changes an operation your connection calls.

On the connection's Overview, find Provider notices and enter the document's address under Published contract. Owners and admins can save, replace or remove it.

RuleDetail
FormatAn OpenAPI 3 document in JSON. YAML is not read
AddressPublic HTTPS. An address with sign-in details or a query string is refused, because it is stored and shown as typed
Connection typeHTTP API and webhook connections
SizeUp to 5 MB and 2,000 operations
ScheduleFetched within a few minutes of saving, then once a day
One per connectionReplacing the address starts a fresh baseline

Seamward fetches the address from its own servers. The request carries nothing that identifies your workspace, redirects are not followed, and an address that resolves to a private network is refused.

The first fetch is a baseline and raises nothing. If a fetch fails, the last version read is kept, the card shows why, and Seamward tries again at widening intervals of up to a week. A failed fetch never raises an advisory.

This is separate from the contract you register: watching a published document does not activate it, and an advisory does not change which contract observations are compared with.

Diagnose a mismatch

When registered operations do not match observations, compare these fields in order:

  1. Integration direction and protocol.
  2. HTTP method and normalized route template.
  3. Event type when the contract declares one.
  4. Payload location: request, response, or message.
  5. Response status selection: exact status, status class, then default.

Use templates such as /customers/{customerId} or /customers/:customerId; Seamward normalizes both forms. If no operation matches, Seamward does not silently claim that an observed baseline is the registered contract. Review the collector metadata and contract selector, then register and activate a corrected immutable version.