Aceby Black Label

Developers

Build on Ace.

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

Your keys

Keys act as your account. Keep them secret; revoke one any time.

MCP: every app in every chat

Ace runs a remote MCP server. Any client that speaks MCP gets six tools: search_apps, connect_app, list_connections, find_tools, get_tool, run_tool.

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

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

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

SDKs

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

Install
npm install https://tryacee.com/sdk/tryacee-sdk-1.0.0.tgz
JavaScript
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 🎉",
});

REST API

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 at /openapi.json.

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.

JavaScript
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"]));