# Publish an app API

Explicitly select public operations and fields before releasing an app contract.

## Choose the public surface

An app's internal operations can change with its implementation. Publishing an operation creates a customer contract with a separate release decision. Mark a resource or authored operation with `external: { "stability": "stable" }` in the app manifest's `api` block.

Select each public field with `api: true` in its `FieldSpec`. This applies to resource fields and to an authored operation's request and response fields. Declared nested object fields also need their own `api: true`. New internal fields remain private until explicitly selected and released.

For example, this manifest declaration publishes an authored query:

```json
{
  "api": {
    "operations": {
      "ReadMetrics": {
        "kind": "query",
        "description": "Read the number of open tickets.",
        "external": { "stability": "stable" },
        "input": {
          "queue": { "type": "string", "api": true }
        },
        "output": {
          "count": { "type": "number", "api": true }
        }
      }
    }
  }
}
```

Implement the matching `ReadMetrics` handler in the app's `api.ts`. With the assigned namespace `helpdesk`, this operation is published as
`apps.helpdesk.ReadMetrics`. Use that name over HTTP or MCP. The handler and
internal app calls continue to use `helpdesk.ReadMetrics`. Publishing the manifest does not create the handler or grant credentials access to it.

## Validate and release

Validate the app and review the external schema before saving the release. A required input field cannot be kept private: callers need every required input to invoke the operation. Validation refuses such a contract rather than exposing that field automatically.

Saving a release makes its approved public contract available to authenticated discovery and workspace OpenAPI generation. Draft changes remain internal. Existing keys and MCP grants still need approval for any newly added operations or resource access.

Copied and installed apps start with their own publication boundary. Their inherited manifest declarations do not expose an API automatically. Validate and save a release to approve that app's public contract, then choose the operations in the credential's permissions. Discovery uses the frozen contract registered for the current saved version, so later changes to internal schema generators cannot rewrite it.

## Evolve the contract

Add optional inputs and compatible outputs while retaining supported behavior. Removing a promised field or operation, narrowing accepted inputs, or widening a response enum can break existing integrations. Publication checks compare against supported released contracts, including contracts added by later app releases.

Rolling an app back cannot erase a contract customers already use. Keep the supported operation available while replacing the underlying feature, or follow the [retirement policy](https://developer.brigg.app/versioning) with a migration path and at least 30 days of notice for stable contracts.

