Skip to main content
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

CallerUseWhy
AI agent in Claude Desktop / Cursor / ChatGPTMCPOAuth 2.1, 15 tools curated for context efficiency, instructions auto-loaded
Your application code (Node, Python, Go, etc.)REST + TypeScript SDKFull surface, generated typed client, idempotency keys
Human at a terminal — one-off lookups, key management, log tailingCLI (salty)Browser OAuth, OS keychain, salty logs tail
External system that needs to react to changesWebhooksSigned (HMAC-SHA-256), retried with backoff, auto-deactivated on 8 fails

Detailed comparison

REST APIMCPCLIWebhooks
URL / host$SALTY_API (api.trysalty.com/v1)$SALTY_MCP/mcplocal — salty binaryyour URL (passed on subscribe)
TransportHTTPS JSONHTTPS JSON (Streamable HTTP, stateless)HTTPS via OAuth-bearerHTTPS POST from Salty to you
AuthAuthorization: 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 size34 endpoints, full CRUD on everything15 curated tools (no delete_* by design)9 command groupsevents for every object’s create/update/delete + schema mutations
Paginationcursor (next_cursor)cursor (returned in tool output)cursor (auto-paginated via --limit)one event per delivery
IdempotencyIdempotency-Key header (24h)inherited via REST forwardinheriteddelivery_id for receiver-side dedupe
Rate limitper-workspace token bucket (plan tier)same — inheritedsameinbound: rate-limited at delivery worker (~50 req/s to a single endpoint)
Usage capmeters agent traffic, exempts JWT adminmeters (MCP forwards)meters (CLI uses OAuth)doesn’t count — outbound only
Schema introspectionGET /schemaget_schema toolsalty schema showN/A
Audit logevery call lands in api_call_logsamesamewebhook_deliveries table

Decision tree

Is the caller a human, an AI agent, or another machine?
  • Human (you) at the terminal → CLI. salty login once, then salty 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.
You’ll often use multiple surfaces in the same product. Common pattern: a backend service writing via REST, an AI agent reading + writing via MCP, your alerting hooked up via webhooks, and you on the CLI for ops.

Common workflows by surface

TaskRESTMCPCLI
Create a personPOST /peoplecreate_personsalty people create --email …
List people with filterGET /people?filter=…search_peoplesalty people list --limit 50
Get a single personGET /people/:idget_personsalty people get <id>
Patch a personPATCH /people/:idupdate_person(REST only)
Add a schema attributePOST /schema/:type/attributesadd_attributesalty schema add-attribute --object person --key tier --type enum --values free,pro,enterprise
Log a meetingPOST /activitieslog_activity(REST only)
Create a taskPOST /tasks(no MCP tool by design)(REST only)
Register a webhookPOST /webhook-endpoints(no MCP tool by design)salty webhooks add --url … --events …
Define a custom objectPOST /custom-objects(no MCP tool by design)(REST only)
Tail the audit logGET /workspace/usage-logs(no MCP tool)salty logs tail
Check usageGET /workspace/usage(no MCP tool — admin surface)salty usage
Why is the MCP surface smaller? More tools = larger context window pollution = worse agent performance. Deletion, task creation, webhook registration, custom-object definition, and usage queries are all admin-ish operations a human should drive. The 15 MCP tools are the agent’s day-to-day write surface; everything else goes through REST or CLI where a human can review.

Latency profile

All four surfaces hit the same Postgres in the same region — so end-to-end latency depends on which middleware chain runs:
SurfaceTypical hot-path latency (p95)
REST30-50ms
MCP50-90ms (REST + JSON-RPC marshalling)
CLI80-200ms (includes OS keychain lookup + HTTPS)
Webhook delivery1-3s end-to-end (worker tick + receiver RTT)
Per-plan rate-limit ceilings are validated under load with k6.

Mixing surfaces

A typical solopreneur stack might look like:
┌──────────────────────────────────┐
│  Claude Desktop / Cursor         │
│  → MCP (15 tools, OAuth)         │
└──────────────────────────────────┘


┌──────────────────────────────────┐
│  Your backend (Node/Python)      │
│  → REST API (SDK or curl)        │
└──────────────────────────────────┘


┌──────────────────────────────────┐         ┌─────────────────────┐
│  Salty API + Postgres             │ ──────► │  Your webhook       │
│                                  │ signed  │  receiver           │
└──────────────────────────────────┘ HMAC    └─────────────────────┘


┌──────────────────────────────────┐
│  You at the terminal             │
│  → CLI (salty login, salty logs)   │
└──────────────────────────────────┘
Every interaction is logged. Every state change fires events. Every surface respects the same plan caps and rate limits.