Cotal Send API
The Send API from Cotal — 1 operation(s) for send.
The Send API from Cotal — 1 operation(s) for send.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/cotal-ai:cotal-ai-send-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Cotal Ai Send API
version: '1'
license:
name: Apache-2.0
description: 'Operations tagged Send across 2 of this provider''s published API definitions: cotal-ai-dashboard-openapi.json, cotal-ai-dashboard-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: http://{host}:{port}
description: Your dashboard listener. Broker TLS does not encrypt this HTTP connection.
variables:
host:
default: 127.0.0.1
port:
default: '7799'
security:
- DashboardSession: []
- LaunchToken: []
tags:
- name: Send
paths:
/api/send:
post:
operationId: send-as-operator
summary: Post as the operator
description: 'Post one message as the operator the process holds: {kind: "msg", channel, text} to one concrete channel, or {kind: "dm", to, text} to one roster member. The body is read before any refusal, so the 8192-byte cap bounds what a refused post costs, and every check runs before the poster starts, so a refused post never puts the operator on the roster. A wildcard or alias channel, an id not on the roster, an empty text, another kind, or a body that is not a JSON object is refused with 400. A read-only service, an expired operator credential and a cross-origin request answer 403 with the reason. A publish the broker refuses answers 502 with the refusal. Other methods fall through to 404.'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
kind:
type: string
enum:
- msg
- dm
channel:
type: string
minLength: 1
description: The channel, for kind msg. One concrete channel; no wildcard.
to:
type: string
minLength: 1
description: The roster member's agent id, for kind dm.
text:
type: string
minLength: 1
description: The message. Trimmed; an empty text is refused.
required:
- kind
- text
examples:
channel:
value:
kind: msg
channel: general
text: Ship it.
dm:
value:
kind: dm
to: local.UACCAXW2KQKIQGMNYJFHWTWZSKA3J2TF7EFCABLCXS5UIZATMT345EWS
text: How long until the smoke is green?
responses:
'200':
description: The post went out.
content:
application/json:
schema:
$ref: '#/components/schemas/SendAnswer'
'302':
$ref: '#/components/responses/LaunchExchange'
'400':
description: The target, the text, the kind or the body was refused; the error names which.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
$ref: '#/components/responses/Unauthenticated'
'403':
description: A browser origin was refused (cross-origin), the service is read-only (post is off in /api/meta), or the operator credential expired.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
$ref: '#/components/responses/BodyRefused'
'500':
$ref: '#/components/responses/InternalError'
'502':
description: The broker refused the publish; the error carries the refusal as it came.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: The dashboard is shutting down, so it no longer posts.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Send
servers:
- url: http://{host}:{port}
description: Your dashboard listener. Broker TLS does not encrypt this HTTP connection.
variables:
host:
default: 127.0.0.1
port:
default: '7799'
components:
responses:
Unauthenticated:
description: No valid session, an invalid launch token, or a spent launch token. The readiness credential does not authorize these routes.
content:
application/json:
schema:
$ref: '#/components/schemas/AuthenticationError'
example:
error: unauthenticated
LaunchExchange:
description: A valid one-use k query token is exchanged for a dashboard session. The response redirects to the same path without its query. A valid existing cookie takes precedence over k.
headers:
Location:
schema:
type: string
description: The requested path without the query string.
Set-Cookie:
schema:
type: string
description: cotal_web_session=<session>; Path=/; HttpOnly; SameSite=Strict. The default local listener uses HTTP.
InternalError:
description: The request failed. The body names the failure; a failed read does not terminate the dashboard.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
BodyRefused:
description: These read routes accept no request body. An announced body is refused before it is read; the connection is closed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
AuthenticationError:
type: object
properties:
error:
type: string
enum:
- unauthenticated
- launch-token-already-used
required:
- error
Error:
type: object
properties:
error:
type: string
required:
- error
SendAnswer:
type: object
description: A post that went out. seq is a DM's stored sequence, the broker's proof that it kept the message; a channel post has none.
properties:
ok:
type: boolean
enum:
- true
id:
type: string
description: The message id.
operatorId:
type: string
description: The operator's agent id, the same id /api/meta reports.
seq:
type: integer
minimum: 1
required:
- ok
- id
- operatorId
additionalProperties: false
securitySchemes:
DashboardSession:
type: apiKey
in: cookie
name: cotal_web_session
description: Process-local dashboard session issued by the one-use launch URL.
LaunchToken:
type: apiKey
in: query
name: k
description: One-use bootstrap token from the owner-private launch URL. It returns HTTP 302 with a session cookie rather than the requested data.
ReadinessNonce:
type: apiKey
in: header
name: x-cotal-readiness
description: Private startup readiness nonce, accepted only by /api/meta. It does not create a browser session.
externalDocs:
description: Dashboard setup and access limits
url: https://docs.cotal.ai/watch-a-mesh/#web-dashboard
x-refined-from:
- cotal-ai-dashboard-openapi.json
- cotal-ai-dashboard-openapi.yml
x-source: implementations/auth/src/service.ts ROUTES and loopback handlers