/api/vendo. Every request passes through
principal(req). Bodies use core types encoded as JSON and conversation turns
stream over SSE.
Development routes
These routes are only mounted in development compositions. Production deployments return404 for each of them. They require a host-resolved
principal — anonymous callers receive 401.
MCP door
WithcreateVendo({ mcp: true, oauth }), the door serves its transport under
the wire plus four origin-root discovery documents through the same handler.
Bodies follow the MCP transport spec, not the wire’s JSON envelope.
With
remoteAs configured, /api/vendo/mcp/authorize, /token, /register,
and the RFC 8414 authorization-server metadata all return 404; the external
issuer owns those endpoints and RFC 9728 metadata advertises it. See MCP
door for the delegation model.
Door paths bypass the wire’s principal resolver and CSRF JSON gate. The door
re-resolves oauth.principal(subject) on every bearer-authenticated transport
request, so returning null revokes live sessions; the OAuth and discovery
endpoints are not principal-resolved. The origin-root discovery documents sit
outside /api/vendo; opting into MCP during vendo init generates the sibling
Next.js route that forwards them to the same handler. See MCP
door for the generated placement and manual fallback.
Webhook verification
Every source registers verification during wiring. Connector sources use their own signed headers. Self-minted sources use HMAC-SHA256 overid.timestamp.rawBody, with signature, timestamp, and delivery id in headers.
The accepted clock window is five minutes. Delivery ids are deduplicated.
A verification failure returns 401, resolves no principal, starts no run, and
writes one audit event. The secret never appears in a URL. No wire route is
unauthenticated.
Organization context
Approvals and grants take an optional?org=<orgId> query parameter (or
body.org on POSTs) to operate under an organization’s subject instead of
the caller’s user subject. Members of the org may list; admins and owners
may decide, grant, or revoke. Non-members see 404; members without the
required role see 403. Without an entitled VENDO_API_KEY, the entire
/orgs route family and every ?org= variant return cloud-required
(402). See Principals and organizations.
Errors and CSRF
Every non-2xx response uses{ "error": { "code", "message" } }. Statuses are
400 validation, 404 not found, 403 blocked, 409 conflict, 402 cloud required,
and 501 sandbox unavailable or not implemented.
Cookie-authenticated mutations require Content-Type: application/json.
Binary app import, signed webhooks, and bearer-authenticated tick are the only
exceptions. MCP door paths sit outside both rules; they speak MCP and OAuth
response shapes, not the wire envelope.