# Publish an API

Start with [Getting started](/docs/getting-started) for a complete hello world
example. This page covers the publishing contract and Claude Code MCP setup.

## Choose the destination [#choose-the-destination]

Before publishing, show and confirm these three values:

```text
Account:    ada
API slug:   billing
Visibility: private
```

Use your personal account handle, or an organization handle if you are a
member. The slug must be a lowercase URL slug. **Set visibility to `private` or
`public` explicitly** on every publish. If the API already exists, visibility
must match its current setting. Publishing cannot change an API's visibility;
use an authorized metadata update for that.

## Create a publishing token for REST or CI [#create-a-publishing-token-for-rest-or-ci]

In [Settings → Access tokens](https://skmtc.dev/settings/tokens), select
**Generate new token**, name it, set an expiration, and select
`publish:schemas`. Copy the secret immediately; it will not be shown again.
The token lets its owner publish schemas and read APIs, but does not grant
metadata updates or bulk catalog import. Keep it out of source control and
rotate or revoke it from Settings when needed.

For an organization destination, create or join the organization under
[Settings → Organizations](https://skmtc.dev/settings/organizations) first.

## Publish with REST [#publish-with-rest]

Set `SKMTC_TOKEN` in your shell or CI secret store. Send the raw OpenAPI JSON
or YAML document:

```sh
curl --fail-with-body \
  --request POST \
  --header "Authorization: Bearer $SKMTC_TOKEN" \
  --header 'Content-Type: application/octet-stream' \
  --data-binary @openapi.yaml \
  'https://api.skmtc.dev/v1/apis/publish?owner=ada&slug=billing&visibility=private&filename=openapi.yaml'
```

Replace `ada`, `billing`, and the filename with your own values. Successful
publishing creates an API or a new revision. Repeating identical content does
not create a duplicate revision. If the same document belongs to a different
slug under that account, the request returns a conflict.

`POST /v1/apis/publish` requires `owner`, `slug`, and `visibility` every time.
The older `/v1/apis/upload` endpoint is for catalog ingestion and still
defaults a new API to public if visibility is omitted. Use `/publish` for your
own schemas. The REST endpoint accepts files up to 50 MB.

## Publish from Claude Code [#publish-from-claude-code]

Add the publishing MCP endpoint:

```sh
claude mcp add --transport http skmtc https://mcp.skmtc.dev/mcp/publish
```

Run `/mcp` in Claude Code, choose **skmtc**, then sign in with GitHub in your
browser. Approve `publish:schemas` on the Skmtc consent screen. Claude Code
handles the authorization and token refresh. A personal access token is not
needed for this interactive flow. The public `https://mcp.skmtc.dev/mcp`
endpoint also supports anonymous catalog searches.

To disconnect an agent later, open [Settings → Access tokens](https://skmtc.dev/settings/tokens)
and select **Revoke access** under **Connected apps**. This stops token refresh.
An access token already issued can work for up to one hour.

The `publish_schema` tool creates an API or publishes a revision. The
`publish_revision` tool checks that an existing API has the visibility you
specified. Both require the account, slug, visibility, complete schema text,
and `confirm: true`. Ask Claude to show you the destination and get your
approval before using either tool. MCP accepts schema text up to 1 MB; use
REST for larger files.

The `confirm` field does not independently prove human approval. Review the
account, slug, and visibility in Claude Code before allowing the publish tool
to run. Keep visibility explicit; a private API stays private in its Markdown
view too.

For automated publishing, see [Publish from CI](/docs/getting-started/publish-from-ci).
