The AI agent for customer success.

Keply for agents

Keply reads your book of accounts, finds the churn early and the expansion before anyone asks, and drafts the move for a person to approve. This page is how your own agent gets at it, over the Model Context Protocol and a REST API. Point Claude, ChatGPT, or a custom orchestrator at one server URL and it can read account health, find the revenue at risk, push signals, and have Keply draft the save, with a human in the loop by default.

Overview

Three surfaces, one credential:

SurfaceForEndpoint
MCP serverAgents (Claude, ChatGPT, custom)/functions/v1/mcp
REST ingestData pipelines, server-side jobs/functions/v1/ingest
Webhooks outGetting paged on eventsyour endpoint

Authentication

Mint an API key in Settings → Connect an AI tool, which also renders the config for your client with the key already in it. Existing keys are listed, scoped and revoked in Settings → Developers & agents. Keys start with kep_, are shown once, and carry a scope:

ScopeGrants
readThe six read tools over MCP. Refused by every write and send path.
fullAll 13 tools plus the REST ingest API.

Pass the key as a bearer token: Authorization: Bearer kep_…. OAuth sign-in (for one-click connector directories) is coming; the key path stays supported.

Connect over MCP

Transport is Streamable HTTP (JSON-RPC 2.0, protocol 2025-06-18). One stable server URL:

https://api.keply.ai/functions/v1/mcp

Claude / ChatGPT: Settings → Connectors → Add custom connector, paste the URL. Claude Code:

claude mcp add --transport http keply https://api.keply.ai/functions/v1/mcp \
  --header "Authorization: Bearer kep_YOUR_KEY"

Any other MCP client that takes a JSON config:

{
  "mcpServers": {
    "keply": {
      "type": "streamable-http",
      "url": "https://api.keply.ai/functions/v1/mcp",
      "headers": { "Authorization": "Bearer kep_YOUR_KEY" }
    }
  }
}

List the tools, then call one:

curl -X POST https://api.keply.ai/functions/v1/mcp \
  -H "Authorization: Bearer kep_YOUR_KEY" \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
curl -X POST https://api.keply.ai/functions/v1/mcp \
  -H "Authorization: Bearer kep_YOUR_KEY" \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"money_in_play","arguments":{"limit":5}}}'

Tool reference

13 tools. read never modifies anything. write moves data in or creates drafts, but never reaches a customer. act contacts a customer and obeys the account's autonomy dial. Every tool carries MCP behavioral annotations (readOnlyHint / destructiveHint) that match this table.

list_accountsread

List accounts with their latest health tier, health score (0–100) and ARR, most valuable first.

ParameterTypeDescription
tierstringFilter to one tier: healthy | watch | at_risk | critical.
limitnumberMax accounts to return (default 50).
get_accountread

Full Customer 360 for one account: health score + rationale, open risk flags, subscription and renewal, recent signals, recent agent actions, contacts.

ParameterTypeDescription
accountIdstringAccount UUID.
domainstringAccount domain, e.g. acme.com.
namestringAccount name (exact). Pass any one of the three.
search_accountsread

Search accounts by partial name. Returns id, name, domain, tier and ARR.

ParameterTypeDescription
queryrequiredstringName fragment to match.
money_in_playread

The headline audit: total revenue at risk and ready to grow, plus the top accounts driving each side with the amount and the cited reason.

ParameterTypeDescription
limitnumberTop accounts per side (default 10).
list_actionsread

The action queue: drafted saves and upsells awaiting a human send.

ParameterTypeDescription
statusstringFilter: suggested | awaiting_approval | approved | sent | done | rejected. Default: everything not yet sent.
list_risk_casesread

Open risk cases: account, reason, severity, ARR at risk, and any drafted response ready to execute.

No parameters.

ingest_signalwrite

Push a customer-success signal into the same pipeline Keply scores from. Creates the account by domain if unknown.

ParameterTypeDescription
signalTyperequiredstringe.g. ticket, call, nps, payment, champion_left, note.
summaryrequiredstringHuman-readable summary of the signal.
accountIdstringAccount UUID (or pass accountDomain).
accountDomainstringAccount domain, created on the fly if unknown.
accountNamestringName to use if the account is created from a domain.
sentimentnumber-1 (negative) … 1 (positive).
valuenumberOptional numeric value (score, amount, count).
upsert_accountwrite

Create or update an account and its commercial truth from any CRM or billing tool. Matched by id, domain, or name; hand-set fields are never overwritten. The account is re-scored right away.

ParameterTypeDescription
accountIdstringAccount UUID (or pass accountDomain / accountName).
accountDomainstringCompany domain, created on the fly if unknown.
accountNamestringCompany name (used to match or create).
arrCentsnumberAnnual recurring revenue, in cents.
mrrCentsnumberMonthly recurring revenue, in cents.
renewalDatestringRenewal date (ISO, YYYY-MM-DD).
seatsContractednumberContracted seat count.
planstringPlan / tier name.
contractAmountCentsnumberTotal contract value, in cents.
closeDatestringDeal close / signature date (ISO).
contactsarrayPeople on the account: { name, email, title, role? }, role inferred from title if omitted.
draft_savewrite

Have Keply draft a retention save email for an at-risk account. Creates a draft in the action queue; it is NOT sent; a human approves and sends.

ParameterTypeDescription
accountIdrequiredstringAccount UUID.
draft_upsellwrite

Have Keply draft an expansion email for an account that is ready to grow. Creates a draft in the queue, not sent.

ParameterTypeDescription
accountIdrequiredstringAccount UUID.
run_inspectwrite

Run the full inspect loop now: re-score every account, raise risk flags, draft a save for each at-risk account. Returns a summary of what changed.

No parameters.

rescore_allwrite

Re-score every account from current signals only (no drafting). Use after a bulk data load. Returns counts.

No parameters.

execute_actionact

Execute a drafted action through a channel and log it to the outcome ledger. The only tool that contacts a customer; it obeys the account's autonomy dial.

ParameterTypeDescription
actionIdrequiredstringThe drafted action UUID.
channelstringslack | email | copy | manual. Default: slack.
slackChannelstring#channel or @user; blank DMs the connected user.

REST ingest API

POST /functions/v1/ingest with a batch of events: account, usage, or signal. Accounts are created by domain on the fly; every touched account is re-scored inline. Needs a full-scope key. Full schema in openapi.json.

curl -X POST https://api.keply.ai/functions/v1/ingest \
  -H "Authorization: Bearer kep_YOUR_KEY" \
  -H "content-type: application/json" \
  -d '{"events":[
    {"type":"account","accountDomain":"acme.com","arrCents":1200000,
     "renewalDate":"2026-01-31","seatsContracted":25},
    {"type":"usage","accountDomain":"acme.com","event":"weekly_active","trend":-0.4},
    {"type":"signal","accountDomain":"acme.com","signalType":"ticket",
     "summary":"P1 outage","sentiment":-0.6}
  ]}'

Webhooks

Register an HTTPS endpoint in Settings → Developers & agents → Webhooks and pick events: risk.raised, score.changed, renewal.due, outreach.composed. Keply POSTs signed JSON; failed deliveries retry with backoff (up to 6 attempts), and an endpoint that keeps failing is disabled.

The first three are signals. outreach.composed carries the finished subject and body, and it fires when you switch delivery to handoff: Keply decides who to write to and what to say, and your own system puts it in front of the customer. Direct is the default, so nothing changes until you turn handoff on.

POST https://your-app.com/hooks/keply
X-Keply-Event: risk.raised
X-Keply-Delivery: d1f0…
X-Keply-Signature: sha256=<hmac-sha256 of the raw body>

{
  "id": "d1f0…",
  "event": "risk.raised",
  "timestamp": "2026-07-09T12:00:00Z",
  "data": {
    "account": { "id": "…", "name": "Acme", "domain": "acme.com" },
    "reason": "champion_left",
    "severity": "high",
    "arrAtRiskCents": 1200000,
    "detectedAt": "2026-07-09T11:58:00Z"
  }
}

Verify X-Keply-Signature, an HMAC-SHA256 of the raw body keyed by the endpoint's signing secret (shown once at creation):

const crypto = require('crypto');

function verify(secret, rawBody, sig) {
  const expected = 'sha256=' +
    crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Safety & autonomy

  • Drafts never auto-send. draft_save / draft_upsell land in a queue for human approval.
  • One acting tool. execute_action is the only tool that contacts a customer, and it obeys the per-account autonomy dial (observe → draft → act).
  • Least privilege. Read-only keys are refused at every write and send path.
  • Audit log. Every agent action is recorded with identity, timestamp, and result.
  • Transparent schemas. The tool descriptions your agent receives match this page: no hidden instructions or undisclosed side effects. The MCP only accepts tokens issued for it.

Spec files

/.well-known/mcp.jsonMCP server descriptor (name, endpoint, docs). The authoritative tool catalog is the live tools/list.
/openapi.jsonREST ingest API, OpenAPI 3.1.