Salty exposes four interfaces over the same workspace data: REST API, MCP server, CLI, and signed webhooks. They share auth, rate limits, usage caps, idempotency, and audit logging — but they’re built for different callers. This page tells you which one to use when.
TL;DR — which surface for which caller
| Caller | Use | Why |
|---|---|---|
| AI agent in Claude Desktop / Cursor / ChatGPT | MCP | OAuth 2.1, 15 tools curated for context efficiency, instructions auto-loaded |
| Your application code (Node, Python, Go, etc.) | REST + TypeScript SDK | Full surface, generated typed client, idempotency keys |
| Human at a terminal — one-off lookups, key management, log tailing | CLI (salty) | Browser OAuth, OS keychain, salty logs tail |
| External system that needs to react to changes | Webhooks | Signed (HMAC-SHA-256), retried with backoff, auto-deactivated on 8 fails |
Detailed comparison
| REST API | MCP | CLI | Webhooks | |
|---|---|---|---|---|
| URL / host | $SALTY_API (api.trysalty.com/v1) | $SALTY_MCP/mcp | local — salty binary | your URL (passed on subscribe) |
| Transport | HTTPS JSON | HTTPS JSON (Streamable HTTP, stateless) | HTTPS via OAuth-bearer | HTTPS POST from Salty to you |
| Auth | Authorization: Bearer sk_live_… (API key) | Authorization: Bearer salty_oat_… (OAuth 2.1 + PKCE) | OAuth (browser, token in OS keychain) | HMAC signature on inbound request |
| Surface size | 34 endpoints, full CRUD on everything | 15 curated tools (no delete_* by design) | 9 command groups | events for every object’s create/update/delete + schema mutations |
| Pagination | cursor (next_cursor) | cursor (returned in tool output) | cursor (auto-paginated via --limit) | one event per delivery |
| Idempotency | Idempotency-Key header (24h) | inherited via REST forward | inherited | delivery_id for receiver-side dedupe |
| Rate limit | per-workspace token bucket (plan tier) | same — inherited | same | inbound: rate-limited at delivery worker (~50 req/s to a single endpoint) |
| Usage cap | meters agent traffic, exempts JWT admin | meters (MCP forwards) | meters (CLI uses OAuth) | doesn’t count — outbound only |
| Schema introspection | GET /schema | get_schema tool | salty schema show | N/A |
| Audit log | every call lands in api_call_log | same | same | webhook_deliveries table |
Decision tree
Is the caller a human, an AI agent, or another machine?- Human (you) at the terminal → CLI.
salty loginonce, thensalty people list,salty keys create,salty logs tail. Stays out of the way. - AI agent connected via Claude Desktop, Cursor, or ChatGPT → MCP. Drop the config snippet, restart, done. The agent gets server-level instructions automatically.
- Your own application code (a backend service, a script, a worker) → REST. Use the TypeScript SDK for ergonomics, or curl/Postman for one-offs.
- External system reacting to state changes → Webhooks. Subscribe with
register_webhook, verify signatures, react.
Common workflows by surface
| Task | REST | MCP | CLI |
|---|---|---|---|
| Create a person | POST /people | create_person | salty people create --email … |
| List people with filter | GET /people?filter=… | search_people | salty people list --limit 50 |
| Get a single person | GET /people/:id | get_person | salty people get <id> |
| Patch a person | PATCH /people/:id | update_person | (REST only) |
| Add a schema attribute | POST /schema/:type/attributes | add_attribute | salty schema add-attribute --object person --key tier --type enum --values free,pro,enterprise |
| Log a meeting | POST /activities | log_activity | (REST only) |
| Create a task | POST /tasks | (no MCP tool by design) | (REST only) |
| Register a webhook | POST /webhook-endpoints | (no MCP tool by design) | salty webhooks add --url … --events … |
| Define a custom object | POST /custom-objects | (no MCP tool by design) | (REST only) |
| Tail the audit log | GET /workspace/usage-logs | (no MCP tool) | salty logs tail |
| Check usage | GET /workspace/usage | (no MCP tool — admin surface) | salty usage |
Latency profile
All four surfaces hit the same Postgres in the same region — so end-to-end latency depends on which middleware chain runs:| Surface | Typical hot-path latency (p95) |
|---|---|
| REST | 30-50ms |
| MCP | 50-90ms (REST + JSON-RPC marshalling) |
| CLI | 80-200ms (includes OS keychain lookup + HTTPS) |
| Webhook delivery | 1-3s end-to-end (worker tick + receiver RTT) |
Mixing surfaces
A typical solopreneur stack might look like:Related
- REST API → Introduction — conventions, errors, pagination
- MCP → Introduction — 15 tools, OAuth flow
- MCP → Agent guide — the operating manual auto-loaded on initialize
- CLI → Introduction —
salty loginand every command - Webhooks — signature verification, retry schedule, meta-events