# SeaChat Developer Docs Build on the SeaChat Platform API: a single Bearer key over the stable /v1 facade for chat, multimodal, threads, tools, files, documents, and usage, with a typed TypeScript SDK. ## Quick Start ### Install the SDK The TypeScript SDK wraps the public `/v1` API. It ships dual ESM + CJS with bundled types and runs on Node 18+, Bun, Deno, or any runtime with a global `fetch`. ```bash npm install @seachat/platform-sdk # or: bun add @seachat/platform-sdk ``` ### Create the client Every request carries a SINGLE credential: `Authorization: Bearer `. The SDK never also sends `x-api-key`. The base URL defaults to `https://seachat.ai`; all paths live under `/v1`. ```bash import { SeaChat } from "@seachat/platform-sdk"; const client = new SeaChat({ apiKey: process.env.SEACHAT_API_KEY! }); ``` ### Make your first chat call `client.chat.completions.create` posts to `/v1/chat/completions` (OpenAI-compatible). Pass `stream: true` to get an `AsyncIterable` of chunks instead of one result. ```bash const completion = await client.chat.completions.create({ model: "claude-opus-4-8", messages: [{ role: "user", content: "Greet the ocean in one short line." }], max_tokens: 64, }); console.log(completion.choices[0].message.content); ``` ### Or call /v1 directly with curl Every SDK method maps to a plain HTTP route. The same first call over curl, using the same single Bearer credential: ```bash curl https://seachat.ai/v1/chat/completions \ -H "Authorization: Bearer $SEACHAT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-opus-4-8", "messages": [{"role":"user","content":"Greet the ocean in one short line."}], "max_tokens": 64 }' ``` ## Agent Entrypoints - `/llms.txt` - compact page index and rules for agents. - `/llms-full.txt` - full Markdown corpus. - `/api/capabilities.json` - public route catalog with scopes, schemas, and examples. - `/api/openapi.json` - OpenAPI 3.1 public developer API surface. --- # Quick Start Install the SDK, construct a client with one Bearer key, and make your first /v1 chat call (SDK and curl). ## Before you start All production API traffic enters through `https://seachat.ai` on the stable public base path `/v1`. The docs host is separate so developer material does not compete with the product app shell. The Platform API uses a **single credential**: a bearer API key sent as `Authorization: Bearer `. The gateway rejects requests that carry more than one credential type, so never send both `Authorization` and `x-api-key`. The SDK always sends exactly the one Bearer header. Tenancy is **user-scoped**: each key acts as a single user. There is no separate organization or project credential. ## Get an API key API keys are minted at `POST /v1/auth/keys` after an email / web login at `https://seachat.ai`. Create your first key from the account / API-keys area of the SeaChat web app and copy the token immediately; the full secret is shown only once. Once you already have a key, you can mint more programmatically (useful for CI runners or per-service credentials) with `client.authKeys.create`. ```bash export SEACHAT_API_KEY="sk-..." # Mint an additional key from an existing one: curl https://seachat.ai/v1/auth/keys \ -H "Authorization: Bearer $SEACHAT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"label":"ci-runner"}' ``` ## First call with the SDK Install `@seachat/platform-sdk`, construct one client, and reuse it across your app. `client.me.get()` verifies the key; `client.chat.completions.create` runs an OpenAI-compatible completion. ```bash import { SeaChat } from "@seachat/platform-sdk"; const client = new SeaChat({ apiKey: process.env.SEACHAT_API_KEY! }); const me = await client.me.get(); console.log("Authenticated as:", me.subject); const completion = await client.chat.completions.create({ model: "claude-opus-4-8", messages: [{ role: "user", content: "Write a one-line launch checklist." }], max_tokens: 128, }); console.log(completion.choices[0].message.content); ``` ## First call with curl The same request without the SDK. Use the one Bearer header and post to `/v1/chat/completions`. ```bash curl https://seachat.ai/v1/chat/completions \ -H "Authorization: Bearer $SEACHAT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"claude-opus-4-8","messages":[{"role":"user","content":"Write a one-line launch checklist."}]}' ``` ## Common failures `401` means the request reached the gateway but no valid credential was accepted. Re-check `Authorization: Bearer ` and confirm the key is not revoked. `403` means the key is valid but lacks one of the route's required scopes (for example `model:invoke` for inference or `usage:read` for usage). Mint a key with the scopes you need, or read the capability catalog at `/v1/capabilities`. Any non-2xx response throws a `SeaChatError` in the SDK, carrying `status`, `code`, `message`, and `requestId`. Branch on `err instanceof SeaChatError`, then include `requestId` when contacting support. --- # Authentication A single Bearer API key authorizes every /v1 request. Never send two credentials. ## Single credential The SeaChat Platform API uses exactly one credential: a bearer API key sent as `Authorization: Bearer `. SeaGate (the gateway) rejects requests that present more than one credential type, so do not also send `x-api-key`. The SDK is built to send only the one header. Tenancy is user-scoped. Each key acts as a single user; there is no separate organization or project credential and no second token to manage. ```bash import { SeaChat } from "@seachat/platform-sdk"; const client = new SeaChat({ apiKey: process.env.SEACHAT_API_KEY! }); const me = await client.me.get(); // GET /v1/me console.log(me.subject, me.scopes); ``` ## Headers and base URL Send `Authorization: Bearer `. The base URL defaults to `https://seachat.ai`; override it with the `baseUrl` constructor option or the `SEACHAT_BASE_URL` environment variable (for example to point at a local gateway during development). All public paths are under `/v1`. ```bash curl https://seachat.ai/v1/me \ -H "Authorization: Bearer $SEACHAT_API_KEY" ``` ## Scopes Each route enforces a scope: `model:invoke` for chat/responses/multimodal, `usage:read` for usage, `files:write` / `files:read` and `seadb:content:read` / `seadb:content:write` for files and documents, `seatool:read` / `seatool:write` / `tool:invoke` for tools, and `seaplane:read` / `seaplane:write` for threads. Identity, key-management, and discovery routes need only a valid key. Inspect what your key can do with `client.capabilities.list()` (`GET /v1/capabilities`). --- # API Keys Mint, list, and revoke user API keys through the /v1 auth facade. ## Mint a key `POST /v1/auth/keys` creates a programmatic key. The raw `token` is returned only once; store it in a secret manager or environment variable immediately. All fields are optional: `label`, `scopes` (defaults to a curated external-developer scope set derived from your identity), `spendLimitMicros`, and `expiresAt`. ```bash const created = await client.authKeys.create({ label: "ci-runner", scopes: ["model:invoke", "usage:read"], }); console.log(created.token); // the full secret — shown once ``` ## List and revoke `client.authKeys.list()` (`GET /v1/auth/keys`) lists the keys you own. `client.authKeys.revoke(keyId)` (`DELETE /v1/auth/keys/{keyId}`) revokes one. Revoke any key you suspect is leaked. ```bash const keys = await client.authKeys.list(); await client.authKeys.revoke(created.key!.keyId!); ``` ## Mint over curl The same create call without the SDK: ```bash curl https://seachat.ai/v1/auth/keys \ -H "Authorization: Bearer $SEACHAT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"label":"ci-runner","scopes":["model:invoke","usage:read"]}' ``` --- # TypeScript SDK @seachat/platform-sdk — a typed client over the public /v1 API with one Bearer credential. ## Install `@seachat/platform-sdk` ships dual ESM + CJS with bundled TypeScript declarations, so both `import` and `require` work. It is built on the global WHATWG `fetch`; use Node.js 18+, Bun, Deno, or any edge runtime that provides `fetch` (or pass a `fetch` implementation via the constructor). ```bash npm install @seachat/platform-sdk # or: bun add @seachat/platform-sdk / pnpm add @seachat/platform-sdk ``` ## Construct the client Create one client and reuse it. `apiKey` is required and is sent as `Authorization: Bearer `. `baseUrl` falls back to `SEACHAT_BASE_URL` then `https://seachat.ai`. Optional `timeout` (ms), `fetch`, and `defaultHeaders` are also accepted. If `apiKey` is missing the constructor throws immediately. ```bash import { SeaChat } from "@seachat/platform-sdk"; const client = new SeaChat({ apiKey: process.env.SEACHAT_API_KEY!, // required baseUrl: "https://seachat.ai", // optional, defaults shown timeout: 30_000, // optional per-request timeout (ms) }); ``` ## Resource map The typed namespaces map directly onto `/v1` routes: `client.chat.completions` and `client.responses` (inference), `client.models` (discovery), `client.embeddings` / `client.images` / `client.audio` / `client.video` / `client.rerank` (multimodal over `/v1/invoke`), `client.threads` and `client.threads.messages` (conversation), `client.tools` (plugins), `client.files` (artifacts), `client.docs` (documents), `client.usage`, `client.capabilities`, `client.me`, `client.authKeys`, and `client.tasks` (async polling). For anything the typed namespaces do not cover, use the raw escape hatch `client.invoke(path, body?)` → `POST /v1/invoke/{path}`. ## Error handling Any non-2xx response throws a `SeaChatError` carrying `status`, `code`, `message`, `requestId`, and the raw `body`. Timeouts, network failures, and constructor misuse surface as plain `Error`s instead, so branch on `err instanceof SeaChatError` first. ```bash import { SeaChat, SeaChatError } from "@seachat/platform-sdk"; try { await client.me.get(); } catch (err) { if (err instanceof SeaChatError) { console.error(err.status, err.code, err.message, err.requestId); } else { throw err; // network failure, timeout, or programmer error } } ``` --- # Models OpenAI-compatible chat and responses inference, streaming, and model discovery over /v1. ## Chat completions `client.chat.completions.create` posts to `/v1/chat/completions`. Required fields are `model` and `messages`; common options include `temperature`, `max_tokens`, `tools`, `tool_choice`, and `response_format`. The scope is `model:invoke`. ```bash const completion = await client.chat.completions.create({ model: "claude-opus-4-8", messages: [ { role: "system", content: "You are concise." }, { role: "user", content: "Name three primary colors." }, ], max_tokens: 256, }); console.log(completion.choices[0].message.content); ``` ## Streaming Pass `stream: true` and the call resolves to an `AsyncIterable` of chunks (the gateway responds with `text/event-stream`). Read `chunk.choices[0].delta.content` for each token. ```bash const stream = await client.chat.completions.create({ model: "claude-opus-4-8", messages: [{ role: "user", content: "Write a haiku about the sea." }], stream: true, }); for await (const chunk of stream) { const delta = chunk.choices?.[0]?.delta?.content; if (delta) process.stdout.write(delta); } ``` ## Responses API `client.responses.create` posts to `/v1/responses` (OpenAI-compatible Responses payload, passthrough). It also supports `stream: true`, returning an `AsyncIterable` of chunks. ```bash const result = await client.responses.create({ model: "gpt-5.5", input: "Summarize the SeaChat API in one paragraph.", }); ``` ## Discovery `client.models.list()` (`GET /v1/models`) lists available modalities/models. `client.models.get(path)` (`GET /v1/models/{path}`) reads a sub-resource; pass a modality such as `"image"` or `"embedding"` to enumerate that modality's deployment-specific model ids. Filter to `availability.state === "live_ok"` before using one. ```bash curl https://seachat.ai/v1/models \ -H "Authorization: Bearer $SEACHAT_API_KEY" ``` --- # Multimodal Embeddings, rerank, and image/audio/video generation through the single /v1/invoke entrypoint. ## One entrypoint Embeddings, rerank, and media generation have no dedicated OpenAI-style routes; they all reach the single entrypoint `POST /v1/invoke/{modality}/{model}` with scope `model:invoke`. The SDK provides typed wrappers over it, and `client.invoke(path, body?)` is the raw escape hatch. Each wrapper takes the public `model` id as a field and injects it into the URL path. Model ids are **deployment-specific** — there are no fixed ids to copy. Discover one at runtime with `client.models.get(modality)` (filter to `availability.state === "live_ok"`), or read it from a `SEACHAT_*_MODEL` env var; do not hardcode them. ```bash // Discover a usable model id for a modality, then pass it as `model`: const list = await client.models.get("embedding"); // GET /v1/models/embedding const model = list.find((m) => m.availability?.state === "live_ok")?.model; ``` ## Embeddings `client.embeddings.create` → `POST /v1/invoke/embedding/{model}`. `input` accepts a string, an array of strings, or token arrays; optional `dimensions` and `encoding_format` (`"float" | "base64"`) pass through. ```bash const res = await client.embeddings.create({ model, // deployment-specific, discovered above input: ["the quick brown fox", "lorem ipsum dolor sit amet"], dimensions: 1024, }); for (const item of res.data ?? []) console.log(item.index, item.embedding?.length); ``` ## Rerank `client.rerank(params)` (sugar) and `client.reranker.rerank(params)` both post to `POST /v1/invoke/rerank/{model}`. Pass `query`, `documents`, and optional `top_n`. ```bash const ranked = await client.rerank({ model, query: "best practices for caching", documents: ["HTTP cache headers", "How to bake bread", "Cache invalidation"], top_n: 2, }); for (const r of ranked.results ?? []) console.log(r.index, r.relevance_score); ``` ## Images `client.images.generate` → `POST /v1/invoke/image/{model}`, returning a `GeneratedOutput | SubmitResponse`. Use flat provider params (`prompt`, `negative_prompt`, `size`, `n`, `batch_size`, `image` for image-to-image). Each output has a managed `url` and an `artifactRefId` you can use with `/v1/files/{id}`. ```bash const out = await client.images.generate({ model, prompt: "a lighthouse at dawn, watercolor", size: "1024x1024", n: 1, }); for (const item of out.outputs ?? []) console.log(item.type, item.url, item.artifactRefId); ``` ## Audio `client.audio.speech` → `POST /v1/invoke/audio/{model}`. The convenience `input` field (text to synthesize) maps onto the provider `prompt` without clobbering an explicit `prompt`. Song models can also take `lyrics`. ```bash const out = await client.audio.speech({ model, input: "Welcome aboard. Please fasten your seatbelt.", }); for (const item of out.outputs ?? []) console.log(item.mimeType, item.url); ``` ## Video (async) Video is asynchronous. `client.video.generateAndWait(params, options?)` submits with `mode:"submit"`, polls `GET /v1/tasks/{id}` until terminal success, then returns `GET /v1/tasks/{id}/result`. Use `client.video.generate` with `mode:"submit"` plus `client.tasks.get` / `client.tasks.result` / `client.tasks.cancel` to drive the lifecycle yourself. ```bash const result = await client.video.generateAndWait( { model, prompt: "a paper boat drifting down a rain-soaked street", duration: 5 }, { timeoutMs: 300_000, pollIntervalMs: 5_000 }, ); ``` --- # Threads & Conversation Create threads, append messages, and replay the timeline — pure storage, no runtime. ## Pure storage Threads are conversation storage over `/v1/threads`. The facade forces `dispatch:false`, so appending a message is **pure storage** — it never provisions a runtime and never produces an assistant turn. Reads need `seaplane:read`; writes need `seaplane:write`. ## Threads CRUD `client.threads.create` (`POST /v1/threads`), `client.threads.list` (`GET /v1/threads`), `client.threads.get` / `client.threads.update` / `client.threads.delete`, plus `archive`, `fork`, `pin`, and `unpin`. Create returns `{ thread }`. ```bash const created = await client.threads.create({ title: "API integration smoke", metadata: { source: "sdk-example" }, }); const threadId = created.thread!.id; ``` ## Messages `client.threads.messages.create(threadId, body)` (`POST /v1/threads/{threadId}/messages`) appends a message. `content` is required; `role` defaults to `user` and is constrained to non-runtime roles. `clientMessageId` is the idempotency key — the SDK auto-generates a UUID when omitted, and re-posting the same id replays with `status:"duplicate"`. List with `client.threads.messages.list(threadId, query?)`. ```bash await client.threads.messages.create(threadId, { role: "user", content: "Create a release checklist", }); const messages = await client.threads.messages.list(threadId, { limit: 50 }); ``` ## Timeline `client.threads.timeline(threadId, query?)` (`GET /v1/threads/{threadId}/timeline`) replays the append-only event log; `client.threads.timelineWindow(threadId, query?)` returns a windowed slice anchored at `latest` or `before`. ```bash const timeline = await client.threads.timeline(threadId, { limit: 50 }); for (const ev of timeline.events ?? []) console.log(ev.seq, ev.kind); ``` --- # Tools Discover, inspect, and invoke tool plugins through /v1/tools. ## Catalog first `client.tools.list()` (`GET /v1/tools`) returns the plugin catalog and `client.tools.get(pluginId)` (`GET /v1/tools/{pluginId}`) reads one plugin definition. Reads need `seatool:read`. ```bash const catalog = await client.tools.list(); const plugin = await client.tools.get("image.caption"); ``` ## Invoke a tool `client.tools.invoke(pluginId, toolName, body?)` posts to `/v1/tools/{pluginId}/{toolName}/invoke` and requires `tool:invoke`. The body is `{ input, version?, mode? }`. ```bash const result = await client.tools.invoke("image.caption", "caption_image", { input: { imageUrl: "https://example.com/image.png" }, }); ``` --- # Files & Artifacts S3-style presigned uploads and downloads for managed artifacts over /v1/files. ## Upload `client.files.upload(input)` is the convenience that orchestrates the S3-style flow: create a presigned delegation (`POST /v1/uploads`), PUT the bytes to the signed URL, then complete it (`POST /v1/uploads/complete`). `path` is required; `sizeBytes` and the `sha256` the verifier requires are computed for you from the bytes. Only contract fields are forwarded (`path`, `title`, `kind`, `mimeType`, `sourceThreadId`, `sourceMessageId`, `metadata`, `expiresInSeconds`); unknown keys are rejected. Requires `files:write`. ```bash const completed = await client.files.upload({ bytes: "hello from the SeaChat SDK\n", path: "sdk-examples/demo.txt", kind: "binary", }); const fileId = completed.result?.artifact?.id; ``` ## Read metadata `client.files.get(fileId)` (`GET /v1/files/{fileId}`) returns artifact metadata, and `client.files.list(query?)` (`GET /v1/files`) lists artifacts by `prefix`, `kind`, `artifactType`, or `label`. Reads need `seadb:content:read`. ```bash const meta = await client.files.get(fileId); const list = await client.files.list({ prefix: "sdk-examples" }); ``` ## Download `client.files.content(fileId)` (`GET /v1/files/{fileId}/content`) resolves the bytes. The gateway typically streams them inline (`200`) but may return a signed `302` redirect; the SDK returns `{ url, response }` — `url` is the signed `Location` when redirected (else `null`), and `response` carries the bytes either way. ```bash const { url, response } = await client.files.content(fileId); console.log(await response.text()); ``` ## Delete `client.files.delete(fileId)` (`DELETE /v1/files/{fileId}`) deletes artifact metadata. Requires `seadb:content:write`. --- # Documents Markdown/HTML document CRUD and full-text search over /v1/docs. ## Read and search `client.docs.read(path)` (`GET /v1/docs/{path}`, nested segments supported) reads a document; `client.docs.search(query)` issues `GET /v1/docs/_search?q=`. Reads need `seadb:content:read`. ```bash const doc = await client.docs.read("sdk-examples/notes.md"); const hits = await client.docs.search("SeaChat platform SDK"); ``` ## Write and mutate `client.docs.write(path, content)` (`POST /v1/docs/{path}`) writes a string as `text/markdown` or an object as JSON. `client.docs.patch(path, body, op?)` mutates with `op` of `append | edit | sed | patch`. `client.docs.delete(path)` deletes. Writes need `seadb:content:write`. ```bash await client.docs.write("sdk-examples/notes.md", "# Note\n\nHello from the SDK.\n"); await client.docs.patch("sdk-examples/notes.md", { content: "\nAppended.\n" }, "append"); ``` --- # Play Apps Publish static app bundles and create share or launch links for SeaChat Play. ## Create and release Play is implemented in Seaplane, not a separate service. Create an app, prepare a release delegation, upload built static bytes, then complete the release. ## Hosting model Public app hosts use `https://.play.seachat.ai/`. Caddy maps wildcard Play hosts to Seaplane through SeaGate, and Seaplane enforces app access and cache state. --- # Usage & Quotas Read usage attribution for the current key over a required time range. ## Usage summary `client.usage.get({ start, end })` (`GET /v1/usage`) returns the usage summary for the current key. The gateway **requires both `start` and `end`** — each an ISO-8601 timestamp or unix-seconds number; the call fails without a range. The scope is `usage:read`. ```bash const end = new Date(); const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000); const usage = await client.usage.get({ start: start.toISOString(), end: end.toISOString(), }); ``` ## Over curl The same call without the SDK passes both bounds as query parameters: ```bash curl "https://seachat.ai/v1/usage?start=2026-06-22T00:00:00Z&end=2026-06-29T00:00:00Z" \ -H "Authorization: Bearer $SEACHAT_API_KEY" ``` ## Quota source of truth Usage attribution records user, request, provider, modality, model, and route context. API-key policy fields such as `spendLimitMicros` constrain a key, but account quotas remain the source of truth for runtime spend enforcement. --- # Agent-Friendly Docs Machine-readable entry points for code agents, runtime agents, and API explorers. ## Read these first `/llms.txt` summarizes stable docs and reference URLs for language-model agents. `/llms-full.txt` contains the full Markdown corpus in one file. Every page is also emitted as Markdown at `/path/index.md`, and HTML responses advertise the Markdown alternate link. `/api/openapi.json` exposes the public `/v1` developer surface as OpenAPI 3.1 for API clients and code generators. `/api/capabilities.json` is the same catalog with scopes, schemas, and examples. The live gateway also serves `GET /v1/openapi.json` and `GET /v1/capabilities` so an agent can read the contract and its own key's capabilities at runtime. ## Decision rules for agents Use one Bearer credential and never send both `Authorization` and `x-api-key`. Prefer the typed SDK methods or the documented `/v1` paths over guessing internal routes. Discover deployment-specific model ids with `client.models.get(modality)` before sending multimodal params. Keep credentials out of prompts and generated files. --- # API Reference Generated capability index for the public /v1 developer surface. ## Capability index This public developer catalog excludes admin and internal routes. ### DELETE /v1/docs/{path} - id: `platform.docs.delete` - service: `seadb` - group: `documents` - access: `write` - requiredScopes: `seadb:content:write` - runtimeSafe: `false` Delete a document by path. ### PATCH /v1/docs/{path} - id: `platform.docs.patch` - service: `seadb` - group: `documents` - access: `write` - requiredScopes: `seadb:content:write` - runtimeSafe: `false` Mutate a document with op append | edit | sed | patch. ### GET /v1/docs/{path} - id: `platform.docs.read` - service: `seadb` - group: `documents` - access: `read` - requiredScopes: `seadb:content:read` - runtimeSafe: `false` Read a markdown/HTML document by path, or search via /v1/docs/_search?q=. ### POST /v1/docs/{path} - id: `platform.docs.write` - service: `seadb` - group: `documents` - access: `write` - requiredScopes: `seadb:content:write` - runtimeSafe: `false` Write a document as text/markdown (string) or JSON (object). ### GET /v1/files/{fileId}/content - id: `platform.files.content` - service: `seadb` - group: `files` - access: `read` - requiredScopes: `seadb:content:read` - runtimeSafe: `false` Stream artifact bytes inline (200) or return a signed redirect (302). ### DELETE /v1/files/{fileId} - id: `platform.files.delete` - service: `seadb` - group: `files` - access: `write` - requiredScopes: `seadb:content:write` - runtimeSafe: `false` Delete artifact metadata by id. ### GET /v1/files/{fileId} - id: `platform.files.get` - service: `seadb` - group: `files` - access: `read` - requiredScopes: `seadb:content:read` - runtimeSafe: `false` Read artifact metadata by id. ### GET /v1/files - id: `platform.files.list` - service: `seadb` - group: `files` - access: `read` - requiredScopes: `seadb:content:read` - runtimeSafe: `false` List artifact metadata by prefix, kind, artifactType, or label. ### POST /v1/auth/keys - id: `platform.auth_keys.create` - service: `seagate` - group: `auth` - access: `write` - requiredScopes: anonymous/public - runtimeSafe: `false` Create a user-scoped API key. The raw token is returned only once. ### GET /v1/auth/keys - id: `platform.auth_keys.list` - service: `seagate` - group: `auth` - access: `read` - requiredScopes: anonymous/public - runtimeSafe: `false` List the API keys owned by the current user. ### DELETE /v1/auth/keys/{keyId} - id: `platform.auth_keys.revoke` - service: `seagate` - group: `auth` - access: `write` - requiredScopes: anonymous/public - runtimeSafe: `false` Revoke a user-scoped API key by id. ### GET /v1/capabilities - id: `platform.capabilities.list` - service: `seagate` - group: `auth` - access: `read` - requiredScopes: anonymous/public - runtimeSafe: `false` Return the capability catalog available to the current credential. ### GET /v1/me - id: `platform.me.get` - service: `seagate` - group: `auth` - access: `read` - requiredScopes: anonymous/public - runtimeSafe: `false` Return the identity, actor type, auth method, and scopes for the current API key. ### POST /v1/downloads - id: `platform.downloads.create` - service: `seagate` - group: `files` - access: `read` - requiredScopes: `files:read` - runtimeSafe: `false` Create a signed download URL for an artifact. ### POST /v1/uploads/complete - id: `platform.uploads.complete` - service: `seagate` - group: `files` - access: `write` - requiredScopes: `files:write` - runtimeSafe: `false` Finalize a presigned upload; requires the sha256 of the bytes you PUT. ### POST /v1/uploads - id: `platform.uploads.create` - service: `seagate` - group: `files` - access: `write` - requiredScopes: `files:write` - runtimeSafe: `false` Create an S3-style presigned upload delegation. PUT the bytes to the signed URL, then complete. ### POST /v1/threads - id: `platform.threads.create` - service: `seaplane` - group: `conversation` - access: `write` - requiredScopes: `seaplane:write` - runtimeSafe: `false` Create a conversation thread (pure storage; no runtime). ### GET /v1/threads/{threadId} - id: `platform.threads.get` - service: `seaplane` - group: `conversation` - access: `read` - requiredScopes: `seaplane:read` - runtimeSafe: `false` Read a conversation thread by id. ### GET /v1/threads - id: `platform.threads.list` - service: `seaplane` - group: `conversation` - access: `read` - requiredScopes: `seaplane:read` - runtimeSafe: `false` List conversation threads (pure storage). ### POST /v1/threads/{threadId}/messages - id: `platform.threads.messages.create` - service: `seaplane` - group: `conversation` - access: `write` - requiredScopes: `seaplane:write` - runtimeSafe: `false` Append a message to a thread. The facade forces dispatch:false; no runtime, no assistant turn. ### GET /v1/threads/{threadId}/messages - id: `platform.threads.messages.list` - service: `seaplane` - group: `conversation` - access: `read` - requiredScopes: `seaplane:read` - runtimeSafe: `false` List messages in a thread. ### GET /v1/threads/{threadId}/timeline - id: `platform.threads.timeline` - service: `seaplane` - group: `conversation` - access: `read` - requiredScopes: `seaplane:read` - runtimeSafe: `false` Replay the append-only timeline of a thread. ### POST /v1/chat/completions - id: `platform.chat.completions.create` - service: `searouter` - group: `models` - access: `invoke` - requiredScopes: `model:invoke` - runtimeSafe: `false` Create an OpenAI-compatible chat completion. Set stream:true for an SSE stream. ### GET /v1/models/{path} - id: `platform.models.get` - service: `searouter` - group: `models` - access: `read` - requiredScopes: `model:invoke` - runtimeSafe: `false` Enumerate deployment-specific model ids for a modality (filter to availability.state live_ok). ### GET /v1/models - id: `platform.models.list` - service: `searouter` - group: `models` - access: `read` - requiredScopes: `model:invoke` - runtimeSafe: `false` List available model modalities and models. ### POST /v1/responses - id: `platform.responses.create` - service: `searouter` - group: `models` - access: `invoke` - requiredScopes: `model:invoke` - runtimeSafe: `false` Create an OpenAI-compatible Responses result. Set stream:true for an SSE stream. ### DELETE /v1/tasks/{taskId} - id: `platform.tasks.cancel` - service: `searouter` - group: `models` - access: `write` - requiredScopes: `model:invoke` - runtimeSafe: `false` Cancel an in-flight async task. ### GET /v1/tasks/{taskId} - id: `platform.tasks.get` - service: `searouter` - group: `models` - access: `read` - requiredScopes: `model:invoke` - runtimeSafe: `false` Poll an async media/task by id. ### GET /v1/tasks/{taskId}/result - id: `platform.tasks.result` - service: `searouter` - group: `models` - access: `read` - requiredScopes: `model:invoke` - runtimeSafe: `false` Fetch the result of a completed async task. ### POST /v1/invoke/{path} - id: `platform.invoke` - service: `searouter` - group: `multimodal` - access: `invoke` - requiredScopes: `model:invoke` - runtimeSafe: `false` Single entrypoint for embeddings, rerank, and image/audio/video generation. path = {modality}/{model}[/{version}]. ### GET /v1/usage?start={start}&end={end} - id: `platform.usage.get` - service: `searouter` - group: `usage` - access: `read` - requiredScopes: `usage:read` - runtimeSafe: `false` Return usage attribution for the current key. Both start and end are required. ### GET /v1/tools/{pluginId} - id: `platform.tools.get` - service: `seatool` - group: `tools` - access: `read` - requiredScopes: `seatool:read` - runtimeSafe: `false` Read a tool plugin definition by id. ### POST /v1/tools/{pluginId}/{toolName}/invoke - id: `platform.tools.invoke` - service: `seatool` - group: `tools` - access: `invoke` - requiredScopes: `tool:invoke` - runtimeSafe: `false` Invoke a tool by plugin id and tool name with a JSON input. ### GET /v1/tools - id: `platform.tools.list` - service: `seatool` - group: `tools` - access: `read` - requiredScopes: `seatool:read` - runtimeSafe: `false` List the available tool/plugin catalog. ### POST /v1/tools - id: `platform.tools.publish` - service: `seatool` - group: `tools` - access: `write` - requiredScopes: `seatool:write` - runtimeSafe: `false` Publish or register a tool plugin definition.