Developers

Build on Ace.

One key opens every app your account connects — 1,609 of them. Call them from your code, hand them to any AI chat over MCP, or ship them inside your own product.

Your keys

One key per project.

Keys belong to your Ace account and reach the apps you connect on Integrations. Keys act as your account: keep them secret and revoke one any time. A new key is shown once; Ace keeps only a fingerprint and cannot show it again.

ReadList apps, connections, tools
ConnectMake sign-in links, disconnect
RunAct in connected apps

Keys are created on your Ace developer page after you sign in.

MCP

Every app in every chat.

Ace runs a remote MCP server. Any client that speaks MCP gets six tools:

search_appsconnect_applist_connectionsfind_toolsget_toolrun_tool

Claude

Settings → Connectors → Add custom connector. Name it Ace and paste your link:

https://tryacee.com/mcp/k/ace_sk_YOUR_KEY

The link carries your key. Treat it like a password.

Claude Code

In a terminal:

claude mcp add --transport http ace https://tryacee.com/mcp --header "Authorization: Bearer ace_sk_YOUR_KEY"

ChatGPT

Settings → Apps & Connectors → Advanced → turn on Developer mode, then Create. Paste your link and choose No authentication (the link holds your key):

https://tryacee.com/mcp/k/ace_sk_YOUR_KEY

Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "ace": {
      "url": "https://tryacee.com/mcp",
      "headers": {
        "Authorization": "Bearer ace_sk_YOUR_KEY"
      }
    }
  }
}

VS Code

Add to .vscode/mcp.json:

{
  "servers": {
    "ace": {
      "type": "http",
      "url": "https://tryacee.com/mcp",
      "headers": {
        "Authorization": "Bearer ace_sk_YOUR_KEY"
      }
    }
  }
}

Any client

Streamable HTTP at https://tryacee.com/mcp with Authorization: Bearer <key>, or the URL-only form https://tryacee.com/mcp/k/<key>. Server card: https://tryacee.com/.well-known/mcp/server-card.json.

curl https://tryacee.com/mcp \
  -H "Authorization: Bearer ace_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

SDKs

Three lines to a connected app.

No dependencies. JavaScript runs in Node 18+, Deno, Bun, Workers and browsers. Python needs only the standard library.

JavaScript

npm install https://tryacee.com/sdk/tryacee-sdk-1.0.0.tgz
import { Ace } from "@tryacee/sdk";

const ace = new Ace({ apiKey: process.env.ACE_API_KEY });

// 1. Connect an app (send your user to the link once)
const { url } = await ace.apps.connect("slack");

// 2. Find the tool for a task, in plain words
const { tools } = await ace.tools.find("post a message in #sales on Slack");

// 3. Run it
const result = await ace.tools.run("SLACK_SEND_MESSAGE", {
  channel: "#sales",
  markdown_text: "Deal closed 🎉",
});

Python

pip install https://tryacee.com/sdk/tryacee-1.0.0-py3-none-any.whl
from tryacee import Ace

ace = Ace()  # reads ACE_API_KEY

link = ace.apps.connect("hubspot")["url"]           # send the user here once
found = ace.tools.find("create a contact in HubSpot")
result = ace.tools.run("HUBSPOT_CREATE_CONTACT", {"email": "pat@example.com"})

curl

curl https://tryacee.com/api/v1/apps?search=slack \
  -H "Authorization: Bearer ace_sk_YOUR_KEY"

curl -X POST https://tryacee.com/api/v1/tools/SLACK_SEND_MESSAGE/run \
  -H "Authorization: Bearer ace_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"arguments":{"channel":"#sales","markdown_text":"Deal closed"}}'

AI agent

Hand every connected app to your own model. tools.definitions() returns OpenAI or Anthropic tool definitions; pass the model's tool call back to tools.run().

const tools = await ace.tools.definitions({ app: "gmail", format: "anthropic" });

const msg = await anthropic.messages.create({
  model: "claude-opus-5-5",
  max_tokens: 1024,
  tools,
  messages: [{ role: "user", content: "Summarize my unread mail" }],
});

for (const block of msg.content)
  if (block.type === "tool_use") await ace.tools.run(block.name, block.input);

REST API

The whole table.

Base URL https://tryacee.com/api/v1 · Authorization: Bearer ace_sk_… · JSON in and out · errors are {"error":{"code","message"}} · 120 requests a minute per key · full spec in the OpenAPI document.

MethodPathWhat it does
GET/catalogPublic app catalog, no key
GET/apps?search=Search apps with your connection status
GET/apps/{app}One app
POST/apps/{app}/connectSign-in link that connects the app
POST/apps/{app}/requestAny endpoint of a connected app's API: {method, path, query?, body?}
GET/connectionsYour connected apps
DELETE/connections/{id}Disconnect
GET/tools?app=Tools in an app, with input schemas
POST/tools/findFind tools for a task in plain words
GET/tools/{tool}One tool's schema
POST/tools/{tool}/runRun it in a connected app
GET/custom-connectorsYour own connectors (any company's MCP server)
POST/custom-connectorsAdd an MCP server {name, url, key?} or any REST API {name, spec, base?, key?, keyIn?}
DELETE/custom-connectors/{id}Remove it
GET/triggers/types?app=Events an app can send (new payment, new issue, new message…)
POST/triggersWatch one: {type, config?, webhookUrl}, or take webhooks from any service: {source: "webhook", name, webhookUrl?}
GET/triggersYour triggers
DELETE/triggers/{id}Stop watching
GET/events?trigger=The last 50 events and how each delivery went
GET/runsYour 25 latest runs
GET/meThe account behind the key

Triggers

Apps that call you.

Pick an event in any connected app, give Ace your webhook, and every time it happens Ace posts it to you, signed. Ace keeps the last 50 events per trigger and tries each delivery three times.

const { triggers } = await ace.triggers.types({ app: "stripe" });
const { trigger, signingSecret } = await ace.triggers.create({
  type: triggers[0].id,
  webhookUrl: "https://your-app.com/hooks/ace",
});

// In your webhook handler: verify before trusting the body.
import { createHmac, timingSafeEqual } from "node:crypto";
const ts = req.headers["x-ace-timestamp"];
const expected = "sha256=" + createHmac("sha256", signingSecret).update(ts + "." + rawBody).digest("hex");
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-ace-signature"]));
Social media