# deprecate

URL: /business/nouns/interface/deprecate · Id: `verb:Interface.deprecate` · Call: `await $.Interface.deprecate({ … })` (SDK) or the `do` tool at `https://api.sb/mcp`. Inputs says what to pass, Outputs what returns, When it waits who approves.

> Deprecate marks an API version for retirement, posts its sunset date and lists each Tenant still pinned to it.

Deprecate marks an API version for retirement, posts its sunset date and lists each [Tenant](/business/nouns/tenant) still pinned to it.

## Inputs
| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `interface` | [Interface](/business/nouns/interface) | Yes | The API. |
| `version` | `string` | Yes | The version to retire, such as `v1`. |
| `sunsetAt` | `date` | Yes | The date it stops serving, once no Tenant pins it. |

## Outputs
| Output | Type | Required | Description |
| --- | --- | --- | --- |
| `interface` | [Interface](/business/nouns/interface) | Yes | The API, with the version deprecated. |

## Effects
| Fact | Value |
| --- | --- |
| Action class | None: no approval rule names it, so it runs within its seat's Permissions and Limits |
| Stakes | The Startup's own records only |
| Door | Two-way: it runs at once |
| Modes | `try` previews it and stores nothing; `send` returns a pending Action; `do` (default) waits for the result |
| Idempotent | Only with a key: a repeat with the same `Idempotency-Key` and input returns the first Action, the same key with other input is refused with `409`, and a repeat without a key runs again |
| Undo | [Action.undo](/business/nouns/action/undo) reverses it |
| Emits | [`Interface.deprecated`](/business/events/Interface.deprecated) |
| Performed by | The [Engineering Lead](/agents/engineering/engineering-lead) |

- Posts the sunset date to the Changelog and adds `Deprecation` and `Sunset` headers to every response of that version.

## Refuses when
| Check | Error | Fix | Then call |
| --- | --- | --- | --- |
| The key is valid, but its scopes do not allow this operation | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | None. |
| `interface` is missing, or is not a interface | [`invalid-input`](/code/api/errors/invalid-input) | Send `interface` as a interface, then call it again. | None. |
| `version` is missing, or is not a string | [`invalid-input`](/code/api/errors/invalid-input) | Send `version` as a string, then call it again. | None. |
| `sunsetAt` is missing, or is not a date | [`invalid-input`](/code/api/errors/invalid-input) | Send `sunsetAt` as a date, then call it again. | None. |
| The `Idempotency-Key` was sent before with another operation or other input | [`idempotency-mismatch`](/code/api/errors/idempotency-mismatch) | Send a new key for new input; reuse a key only to retry the same request. | None. |

## When it waits
| Gate | Default |
| --- | --- |
| Decision class | Low: two-way, no delay window |
| [Delay window](/systems/trust-and-governance/controls/one-way-windows) | None: it runs once review passes. |
| Limit | The call [Limit](/business/nouns/limit) of the [Permission](/business/nouns/permission) it runs under. |
| Over the Limit | It waits `pending` for an [Approval](/business/nouns/approval), which a Human answers: the owner of record, or a Human they named to approve for the [Founder](/agents/founding/founder) seat. Approved, it runs; refused, it ends `refused` with [`limit-exceeded`](/code/api/errors/limit-exceeded); unanswered by its deadline, it ends `canceled`. |

## Example

**Ask**

```text
Deprecate the latest interface.
```

**API**

```bash
curl -X POST https://api.sb/leaseline.app/interfaces/interface_TMyQ3kh9uX/deprecate \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Idempotency-Key: leaseline-interface-deprecate-1" \
  -H "Content-Type: application/json" \
  -d '{"version":"Example version","sunsetAt":"2026-10-22"}'
```

```json
{
  "api": "https://api.sb/leaseline.app",
  "interface": {
    "$id": "https://api.sb/leaseline.app/interfaces/interface_TMyQ3kh9uX",
    "$type": "Interface",
    "kind": "api"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/act_br07HsG8MG",
    "operation": "Interface.deprecate",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/leaseline.app/actions/act_br07HsG8MG"
  }
}
```

**CLI**

```bash
npx startup-builder do Interface.deprecate --data '{"interface":"interface_TMyQ3kh9uX","version":"Example version","sunsetAt":"2026-10-22"}' \
  --idempotency-key leaseline-interface-deprecate-1
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "code": "return await $.Interface.deprecate({ interface: 'interface_TMyQ3kh9uX', version: 'Example version', sunsetAt: '2026-10-22' })",
    "idempotencyKey": "leaseline-interface-deprecate-1"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const result = await $.Interface.deprecate({ interface: 'interface_TMyQ3kh9uX', version: 'Example version', sunsetAt: '2026-10-22' }, { idempotencyKey: 'leaseline-interface-deprecate-1' })
```

To retry, send the same `Idempotency-Key`: the retry returns the first Action and runs nothing twice. A new key runs the call again.