# External API Guide

Topline's supported customer integration surface is Harness MCP plus the
artifact-app REST endpoints used by the official local MCP package. Internal
browser-session and application UI APIs are not a general customer API.

Use the generated **External API Endpoint Reference** for the authoritative
method/path inventory and **Harness MCP Tool Reference** for tool schemas.
The machine-readable OpenAPI 3.1 contract is available at
`https://topline.build/docs/openapi.json`.

## Base URL and media types

Replace `https://topline.example.com` with the customer's Topline application
origin. Use HTTPS in every non-local environment.

REST endpoints exchange JSON unless an upload endpoint documents multipart or
archive content. Harness MCP uses JSON-RPC over streamable HTTP and accepts
`application/json, text/event-stream`.

## Authentication choices

### OAuth with PKCE (recommended)

Topline publishes OAuth authorization-server and protected-resource metadata.
Clients should discover endpoints rather than hard-code them.

1. Read `/.well-known/oauth-protected-resource/mcp/build` for artifact work or
   `/.well-known/oauth-protected-resource/mcp/workspace` for context work.
2. Read the listed authorization-server metadata.
3. Register a public client with approved redirect URIs.
4. Start authorization with `response_type=code`, the selected MCP resource,
   requested scopes, a PKCE S256 challenge, and caller state.
5. The operator signs in and approves the displayed scopes.
6. Exchange the authorization code and verifier at `/oauth/token`.
7. Refresh before expiry or repeat authorization when refresh is unavailable.
8. Revoke unused access and refresh tokens.

OAuth clients use `token_endpoint_auth_method=none`; PKCE and exact redirect
URI validation protect the public-client flow.

The metadata endpoints also expose `/.well-known/oauth-protected-resource` and
`/.well-known/openid-configuration` as compatibility aliases. Prefer a
product-specific protected-resource path for new integrations.

Authorization requires an active browser session plus the
`mcp.tokens.manage` and `harness.workforce` capabilities.

### OAuth request shapes

Register a client with JSON:

```json
{
  "client_name": "Customer Codex",
  "redirect_uris": ["http://127.0.0.1:49152/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
```

The authorization request uses query parameters: `response_type=code`,
`client_id`, exact `redirect_uri`, `resource`, space-delimited `scope`,
`code_challenge`, `code_challenge_method=S256`, and caller-generated `state`.

Token and revocation requests are form-encoded or JSON objects with the
standard fields. Authorization-code exchange requires `grant_type`,
`client_id`, `code`, `redirect_uri`, `code_verifier`, and `resource`. Refresh
requires `grant_type=refresh_token`, `client_id`, `refresh_token`, and the same
resource. Revocation requires `token`. A successful revocation returns an
empty JSON object even when the token is already unknown.

### Manual connector token

Manual tokens are an advanced fallback created from **Developer Access** by an
authorized operator. Send the token as:

```http
Authorization: Bearer <connector-token>
```

Store it in a secret manager, never source control. Tokens are owner-scoped,
revocable, expire, and are limited to approved scopes.

## Scopes

| Scope | Grants |
| --- | --- |
| `docs:read` | Search and read current product and external API documentation. |
| `chat:read` | List and read bounded, user-visible content from conversations the current operator can access in the current tenant. |
| `harness:artifact:read` | Read artifact deployment status, bounded logs, Storybook access, and handoff URLs. |
| `harness:artifact:write` | Create and update private artifact drafts. |
| `harness:artifact:deploy` | Upload bundles and deploy private drafts. |
| `memory:read` | Read explicit approved operator preferences when the account also has the required capability. |
| `glossary:read` | Look up and resolve approved company terminology when the account also has the required capability. |

Scopes limit the token. Tool handlers also enforce tenant, actor, capability,
task, artifact, and resource ownership where applicable.

## Product MCP endpoints

Use `POST /mcp/build` for artifact tools and `POST /mcp/workspace` for
documentation, conversation, memory, glossary, and company-knowledge tools. Existing clients
may continue using the compatibility union at `POST /mcp/harness`.

OAuth access tokens are audience-bound to one of those exact resources. Manual
connector tokens may be used on either product, but product routing still
prevents cross-surface tool discovery and invocation.

Required headers:

```http
Authorization: Bearer <access-token>
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2025-11-25
```

The current Topline MCP server release is `0.5.0`. Supported protocol versions
are `2025-11-25` and `2025-06-18`. The server
negotiates a supported version during `initialize`. POST bodies are limited to
128 KB and must be single, strict JSON-RPC messages.

### Initialize

```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"customer-client","version":"1.0.0"}}}
```

### Discover tools

```json
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
```

The response includes only tools belonging to the selected product and visible to the token's scopes and the
operator's capabilities. Always discover tools for the active connection.

### Call a tool

```json
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"platform_search_documentation","arguments":{"query":"secure browser MFA","limit":5}}}
```

Read a complete result with its returned ID:

```json
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"platform_read_documentation","arguments":{"id":"secure-browser"}}}
```

MCP notifications do not receive a response. JSON-RPC batches are rejected;
send one MCP message per request. Tool calls are limited to 60 per minute per
connector token and tool, with `Retry-After` on HTTP 429 responses, and hosted
tool calls have a 30-second response deadline.

Workspace discovery and conversation reads require the explicit `chat:read`
scope. `list_workspaces` returns only workspaces visible in the active tenant.
Conversation discovery searches visible titles and recent previews and returns
`nextCursor` for older result pages; `search_conversation_messages`
searches visible text in bounded, cursor-paginated transcript windows. Reads are bounded,
tenant-filtered, and use the same owner, share, and reachable-scope rules as the
Topline chat UI. Read pages include workspace names, `nextBeforeMessageId`, and
per-message truncation flags. Responses include only visible message text and
attachment labels; tool payloads and hidden runtime context are excluded, and
credential-shaped text is masked.

Successful and failed MCP tool calls are recorded by product and tool name
without request arguments. Each active OAuth authorization owns exact success,
failure, and call-count state. Developer Access lists those grants and supports
owner-scoped revocation. Its connection check creates a hashed, single-use,
ten-minute challenge; the external client must call `platform_connection_check`
on the selected product before the browser reports an end-to-end verification.

`/mcp/harness` remains available for compatibility but is deprecated for new
setup. It sends `Deprecation: true` and `Link` headers pointing to `/mcp/build`
and `/mcp/workspace`. No removal date is scheduled.

## Official local MCP package

`@topline-build/harness-mcp` is the Topline Build MCP and runs through stdio inside Codex or Claude Code. It
adds local filesystem packaging for `platform_deploy_artifact_app` while using
the hosted API for authentication and deployment operations.

Use it when the client must package an application directory without sending
the source tree through model tokens. See **Harness MCP Hosting** for setup.

## Artifact-app REST workflow

The local package uses the supported `/api/harness/artifact-apps` routes.

1. Create or update the private draft.
2. Build an allowed `tar.gz` bundle.
3. Upload and start the draft deployment.
4. Poll deployment status.
5. Read bounded redacted logs when necessary.
6. Open the returned Topline handoff and review the draft.
7. Promote through the Topline UI.

Bundles must reject symlinks, absolute paths, parent traversal, `.env*`,
`.git`, `node_modules`, build caches, and configured size violations.

### Create or update a draft

`POST /api/harness/artifact-apps` accepts JSON containing a valid artifact-app
manifest v2. It may be the complete request body or the `manifest` property.
The wrapper also accepts optional `artifactId` (update instead of create),
`title`, `description`, and `projectId`.

```json
{
  "artifactId": "optional-existing-artifact-id",
  "manifest": {
    "manifestVersion": 2,
    "id": "customer-dashboard",
    "title": "Customer dashboard",
    "kind": "dashboard",
    "runtime": { "target": "aws_lambda_function_url", "region": "us-west-2", "entryPoint": "artifactApp" },
    "build": { "command": "npm run build", "outputDir": "dist" },
    "validation": { "localCommand": "npm test" },
    "routes": [],
    "sourceBindings": [],
    "datasets": [],
    "env": [],
    "viewerPolicy": "private"
  },
  "projectId": "optional-project-id"
}
```

Success returns `artifactId`, `artifactVersionId`, `manifestId`, `title`,
`openUrl`, optional `draftUrl`, and `status` (`created` or `updated`). Only an
artifact owned through the same connector identity can be updated.

### Upload a deployment bundle

`POST /api/harness/artifact-apps/{artifactId}/deploy-bundle` sends the tar.gz
bytes as the request body. Use a gzip content type. Optional headers are
`X-Platform-Artifact-Version-Id` and `X-Platform-App-Dir`; the current artifact
version and `.` are used when they are absent.

The endpoint stages a private deployment and returns the bounded deployment
state. Reusing a currently active artifact/version operation can return its
existing state rather than starting competing work.

### Read deployment status

`GET /api/harness/artifact-apps/{artifactId}/deployments` accepts `limit` from
1 through 50 (default 20). It returns the artifact ID and recent deployment
records or the equivalent trusted status projection.

### Read deployment logs

`GET /api/harness/artifact-apps/{artifactId}/logs` supports
`deploymentRecordId`, `environment` (`draft` or `live`), `limit` (1–200,
default 50), `severity`, `contains`, `since`, `windowMinutes`, `trace`,
`requestId`, and `route`. Results are bounded and redacted.

## Developer Access session API

These routes support the Topline Developer Access interface and require an
authenticated browser session plus `mcp.tokens.manage` and
`harness.workforce`:

- `GET /api/harness-connectors` returns current setup metadata and the
  operator's manual connector tokens.
- `POST /api/harness-connectors/tokens` creates a token from `name`,
  `clientKind`, `scopes`, and `expiresInDays` (1–180). The secret token is
  returned once.
- `POST /api/harness-connectors/tokens/{tokenId}/revoke` revokes an owned token.
- `POST /api/harness-connectors/products/{product}/verifications` creates a
  short-lived connection challenge; the paired `GET .../{verificationId}`
  reports `pending`, `verified`, or `expired` without returning the code again.
- `POST /api/harness-connectors/oauth-authorizations/{authorizationId}/revoke`
  revokes an active OAuth grant owned by the signed-in operator.

These are browser-session APIs, not substitutes for OAuth client registration.

## Errors

### HTTP status

| Status | Meaning |
| --- | --- |
| `400` | Invalid JSON, parameters, redirect URI, scope, protocol input, or bundle. |
| `401` | Missing, expired, revoked, or invalid authentication. Inspect `WWW-Authenticate` for OAuth metadata. |
| `403` | Authenticated but missing a scope, capability, tenant, or resource grant. |
| `404` | Unknown route or a resource unavailable within the caller's ownership boundary. |
| `409` | State conflict, such as an incompatible active operation. |
| `413` | Request or bundle exceeds the accepted size. |
| `422` | Valid request shape that cannot be processed by the provider or artifact workflow. |
| `429` | Rate limit reached. Retry according to server guidance with backoff. |
| `500` | Unexpected platform failure. Retry only idempotent operations and retain the request ID. |
| `503` | Required platform integration is not configured or temporarily unavailable. |

### JSON-RPC errors

Protocol errors use JSON-RPC error objects. Tool-level failures can return an
MCP result with `isError: true`. Clients must handle both forms.

Do not respond to `403` by switching to a broader credential. Confirm that the
operator intended to grant the missing authority.

## Idempotency and retries

- Treat reads and tool discovery as retryable with bounded exponential backoff.
- Do not automatically retry deployment creation or uploads unless the API or
  returned state confirms idempotency.
- Preserve OAuth `state`, PKCE verifier, artifact ID, deployment ID, and request
  IDs across the relevant workflow.
- Poll at a bounded interval and stop on terminal state.

## Pagination, limits, and filtering

Use documented `limit`, time-window, severity, and query parameters. Defaults
are intentionally bounded. Do not scrape around limits or request raw provider
logs when the supported tool returns a redacted projection.

## Versioning and compatibility

MCP protocol compatibility is negotiated through `initialize` and the
`MCP-Protocol-Version` header. Tool additions are backward compatible; clients
must not assume a fixed tool list. Removing or changing a stable public tool,
endpoint, required field, or response meaning requires release notes and a
migration period.

Generated references are checked in CI against code-owned metadata. Product
behavior changes must update the relevant hand-written guide in the same pull
request.

## Security requirements

- Use HTTPS and verify the Topline origin.
- Store tokens and refresh tokens only in an approved secret store.
- Never place tokens, cookies, credentials, customer rows, or raw PII in logs,
  prompts, documentation examples, or committed configuration.
- Request the narrowest scopes and revoke unused clients.
- Validate OAuth state and exact redirect URI.
- Treat tool output as tenant data and apply the customer's retention policy.
- Keep live artifact promotion operator-controlled.

## Support evidence

Provide the environment, endpoint or tool name, HTTP status or JSON-RPC error,
timestamp, request ID, artifact/deployment ID when relevant, and a redacted
request summary. Do not provide access tokens, refresh tokens, cookies, typed
browser values, raw logs, or unredacted customer data.
