# Horato documentation Use Horato through REST, SDKs, webhooks, the dashboard panel, and MCP tools. Horato is one communications and scheduling control plane over email, calendar, contacts, tasks, bookings, webhooks, and approval-safe agent actions. ## Choose a surface Use the REST API for server-side product integrations. Use the dashboard panel to operate organizations, applications, API keys, provider connections, billing, and webhook health. Use MCP when an agent needs read tools and approval-gated write tools over the same action model. - REST API: normalized resources, provider IDs, etags, raw payloads, sync cursors, and signed webhooks. - Panel: operational UI for setup, monitoring, billing, keys, and repair workflows. - MCP: resource-safe tools for search, availability, booking, task, and email workflows. ## Base URLs Production API traffic uses `https://api.hora.to`. Public docs live at `https://hora.to/docs`. ### Request shape ```bash curl https://api.hora.to/v1/email/messages \ -H "Authorization: Bearer $HORATO_API_KEY" \ -H "Content-Type: application/json" ``` ## Machine-readable docs OpenAPI, Postman, and LLM text exports are generated from the same docs registry and spec-derived endpoint catalog. - `/docs/openapi.json` for schema-aware tools. - `/docs/postman.json` for manual API exploration. - `/llms.txt` for short agent discovery. - `/docs/llms-full.txt` for a complete plain-text docs snapshot. --- # API usage Authenticate, connect providers, read normalized resources, mutate safely, and replay events. Every REST response uses snake_case fields on the public API surface. Organization and application scoping is derived from the API key. ## Authentication Create an application-scoped API key in the panel. Send it as a Bearer token on every API request. API keys carry scopes, an application_id, and an organization_id. ### Bearer key ```bash curl https://api.hora.to/v1/usage \ -H "Authorization: Bearer $HORATO_API_KEY" ``` ## Provider connection flow Start an OAuth authorization for a provider, redirect the user, then let Horato store the connection and provider tokens. Use capability endpoints before attempting provider-specific operations. ### Start Google authorization ```bash curl -X POST https://api.hora.to/v1/auth/connectors/google/authorize \ -H "Authorization: Bearer $HORATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"scopes":["email.read","calendar.write"],"redirect_uri":"https://app.example.com/oauth/callback"}' ``` ## Read and mutate resources Prefer canonical IDs for stored resources and preserve provider IDs for reconciliation. Mutating calls should include etags when the resource surface exposes conflict control. ### Read messages ```bash curl "https://api.hora.to/v1/email/messages?connection_id=conn_123&limit=25" \ -H "Authorization: Bearer $HORATO_API_KEY" ``` ### Create calendar event ```bash curl -X POST https://api.hora.to/v1/calendars/cal_primary/events \ -H "Authorization: Bearer $HORATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"connection_id":"conn_123","title":"Intro call","start":"2026-06-10T16:00:00Z","end":"2026-06-10T16:30:00Z"}' ``` ## Pagination and idempotency List endpoints return `next_cursor` when more results exist. Write endpoints should send an `Idempotency-Key` header for retry-safe creation when the client may retry after network failures. --- # API reference Endpoint catalog generated from specs.json. This reference mirrors the current product spec. It is intentionally compact so humans and LLMs can scan domains quickly. ## Reference artifacts Download the machine-readable reference when you need schema-aware clients or external tools. The page view groups endpoints by domain. - /docs/openapi.json - /docs/postman.json - /docs/llms-full.txt --- # Panel usage Operate organizations, applications, provider connections, API keys, webhooks, MCP approvals, and usage from the Horato panel. The panel is the human control surface for setup and operations. It should be used for onboarding, live health checks, key rotation, billing checks, and webhook repair. ## Start with organization and application scope Choose the organization first, then select the application that owns the API key and provider connections. Every API request and panel action should be interpreted inside that application scope. - Use one application per product environment when staging and production have different providers. - Rotate API keys from the same application that serves production traffic. - Keep account metadata stable so billing and usage charts remain coherent. ## Connections and provider health Use the connections panel before debugging sync or send errors. A connection can be active, degraded, revoked, or incomplete depending on provider token state and capability coverage. - Check provider, account, status, last sync, and capability flags. - Use refresh only when credentials exist and the provider supports the requested capability. - When a provider returns unsupported behavior, expect `provider_capability_not_supported` rather than a silent fallback. ## API keys and usage Create least-privilege keys for production workers and separate keys for local development. Review usage limits before enabling high-volume sync or webhook replay jobs. ## Webhook inspection and repair Use webhook delivery views to inspect status, attempts, latency, response code, and dead-letter state. Replay only after the receiving endpoint is fixed. ## MCP approvals and run history Read-only tools can execute directly. External writes, email send, booking changes, and destructive operations should create approval records that are visible in the panel and linked to run history. --- # MCP usage Register Horato as an MCP server and expose resource-safe tools to agent runtimes. MCP tools use the same action model as REST. Read tools are safe by default; write tools should be approval-gated when they affect external users or provider state. ## Tool model Tools are thin bindings over Horato resources. The tool catalog should include the input schema, capability requirement, approval policy, and output shape. - `email.search` reads messages and threads. - `calendar.availability` reads free/busy and booking availability. - `booking.create` creates or holds a booking. - `email.send` requires approval before sending externally visible mail. ## Server configuration Set the API key and base URL in the MCP server environment. ### MCP server environment ```bash HORATO_API_KEY=hr_live_... HORATO_API_BASE_URL=https://api.hora.to ``` ### Agent config ```json { "mcpServers": { "horato": { "command": "npx", "args": ["@horato/mcp"], "env": { "HORATO_API_KEY": "hr_live_..." } } } } ``` ## Approval policy Require approval for operations that send messages, create bookings, modify events, delete data, rotate keys, replay deliveries, or start data export jobs. ### Approval-gated write ```typescript tools.register("email.send", { requiresApproval: true, inputSchema: sendEmailSchema, handler: horato.mcp.email.send }); ``` ## Run history Every agent run should be visible through `/v1/mcp/runs` and linked to approvals, provider operations, and webhook events. Use run replay for repair workflows after a transient provider failure. --- # Webhooks Receive signed events, inspect delivery attempts, replay failed deliveries, and requeue dead-lettered events. Horato emits domain events after provider sync, API writes, approvals, booking lifecycle changes, and operational jobs. ## Signature verification Verify the timestamp and signature before processing an event. Reject stale timestamps to reduce replay risk. ### Node verification sketch ```javascript import { verifyHoratoWebhook } from "@horato/unified"; const verified = verifyHoratoWebhook({ rawBody, signature: req.headers["horato-signature"], secret: process.env.HORATO_WEBHOOK_SECRET }); ``` ## Delivery repair Use the delivery inspector when a receiver returns a non-2xx status. Fix the receiver, replay the delivery, then clear dead-letter queues intentionally. - List deliveries with `/v1/webhooks/deliveries`. - Replay one delivery with `/v1/webhooks/deliveries/{delivery_id}/replay`. - Requeue dead-lettered events with `/v1/webhooks/dead-letter/{event_id}/requeue`. --- # SDKs Use typed JavaScript and Python clients when you want request helpers, pagination, and webhook verification. The SDKs wrap the same REST API and keep public field names aligned with snake_case API responses. ## JavaScript Use the JavaScript client in server-side Node runtimes. ### Read messages ```javascript import { Horato } from "@horato/sdk"; const horato = new Horato({ apiKey: process.env.HORATO_API_KEY }); const messages = await horato.email.messages.list({ connection_id: "conn_123" }); ``` ## Python Use the Python client for workers, data repair, and internal automation. ### Query free/busy ```python from horato import Horato client = Horato(api_key=HORATO_API_KEY) slots = client.calendar.free_busy.query(connection_id="conn_123", calendar_ids=["primary"]) ``` --- # Errors Handle validation, auth, conflict, capability, provider, and rate-limit errors consistently. Errors return stable codes and request IDs. Provider-specific unsupported behavior should return `provider_capability_not_supported`. ## Envelope Every error returns an `error` object with a stable code and human-readable message. ### Error response ```json { "error": { "code": "provider_capability_not_supported", "message": "Provider has no tasks support.", "request_id": "req_123" } } ``` ## Common codes Clients should branch on the code, not on the message. - `bad_request`: invalid input or missing field. - `unauthorized`: missing or invalid API key. - `forbidden`: key lacks scope or session policy blocks the action. - `not_found`: resource is not in the current organization/application scope. - `conflict`: stale etag, revoked connection, or incomplete authorization. - `rate_limited`: retry after the documented limit window. --- # Sync Use provider cursors, webhook repair, and replayable jobs to keep canonical data current. Horato normalizes common fields while preserving provider IDs, etags, sync tokens, raw payloads, and capability flags. ## Incremental sync Provider deltas update canonical rows and emit internal events before customer webhook delivery. Store the `next_cursor` or sync checkpoint returned by list and sync surfaces. ## Repair workflow When a provider invalidates a cursor, start a repair sync for that connection and resource. Use webhook delivery replay after downstream systems are ready to consume repaired events. ### Queue sync repair ```bash curl -X POST https://api.hora.to/v1/sync/connections/conn_123/email \ -H "Authorization: Bearer $HORATO_API_KEY" ```