@maton/sdk
v0.1.0
Published
Official TypeScript SDK for Maton — connect and automate 150+ apps from Node.js.
Readme
Maton TS SDK
Official TypeScript / JavaScript SDK for Maton — connect and automate apps (Gmail, Slack, GitHub, Notion, HubSpot, and more).
npm install @maton/sdk
# or
pnpm add @maton/sdk
# or
yarn add @maton/sdkQuickstart
import { Maton } from "@maton/sdk";
const maton = new Maton({ apiKey: process.env.MATON_API_KEY });
const conn = (await maton.connection.create({ app: "gmail" })) as { id: string };
const connectionId = conn.id;
const gmail = maton.google_mail({ connection: connectionId });
const messages = await gmail.message.list({ q: "is:unread", maxResults: 10 });
await gmail.message.send({
to: "[email protected]",
subject: "hi",
body: "hello",
});The same pattern works for every supported app:
const slack = maton.slack({ connection: slackConnId });
await slack.message.send({ channel: "#general", text: "deploy finished ✅" });
const gh = maton.github({ connection: ghConnId });
await gh.issue.create({
repo: "maton-ai/maton-ts",
title: "bug: ...",
body: "...",
});
const notion = maton.notion({ connection: notionConnId });
await notion.data_source.query({
dataSourceId: "...",
filter: { property: "Status", status: { equals: "Done" } },
});
const hubspot = maton.hubspot({ connection: hubspotConnId });
await hubspot.contact.list({ limit: 25 });Generic passthrough:
await maton.api.post("google-mail", "/gmail/v1/users/me/messages/send", {
json: { raw: "..." },
connection: connectionId,
});Triggers
const trigger = (await maton.trigger.create({
source: "github",
eventType: "pull_request.opened",
connectionId: ghConnId,
parameters: { repo: "maton-ai/cli" },
destinations: [{ url: "https://example.com/hook" }],
})) as { trigger: { trigger_id: string } };
const triggerId = trigger.trigger.trigger_id;
await maton.trigger.list({ source: "github", status: "ENABLED" });
await maton.trigger.update({ triggerId, status: "DISABLED" });
const dst = (await maton.trigger.destination.create({
triggerId,
url: "https://example.com/hook",
})) as { destination: { destination_id: string } };
await maton.trigger.destination.rotateSecret({
triggerId,
destinationId: dst.destination.destination_id,
});
const events = (await maton.trigger.event.list({ triggerId, limit: 20 })) as {
events: { event_id: string }[];
};
await maton.trigger.event.replay({ triggerId, eventId: events.events[0].event_id });
for await (const event of maton.trigger.event.watch({ triggerId })) {
handle(event);
}Supported apps (v0.1)
| App | Accessor | Highlights |
|---|---|---|
| Asana | maton.asana | projects, tasks, workspaces |
| GitHub | maton.github | repos, issues, PRs, releases, labels |
| Google Ads | maton.google_ads | accounts, campaigns, ad groups, ads, keywords |
| Google Calendar | maton.google_calendar | calendars, events, ACL, freebusy |
| Google Docs | maton.google_docs | documents (create / get / write) |
| Google Drive | maton.google_drive | files, drives, permissions, comments, revisions |
| Google Mail | maton.google_mail | drafts, labels, messages, threads |
| Google Sheets | maton.google_sheets | spreadsheets, sheets, values |
| Google Tasks | maton.google_tasks | tasklists, tasks |
| HubSpot | maton.hubspot | contacts, companies, deals, associations |
| Jira | maton.jira | issues, projects, transitions, comments, users |
| Linear | maton.linear | issues, projects, cycles, teams (GraphQL) |
| Microsoft Teams | maton.microsoft_teams | teams, channels, chats, messages, meetings |
| Notion | maton.notion | pages, databases, data sources, blocks, search |
| OneDrive | maton.one_drive | drives, items (upload, share, move) |
| Outlook | maton.outlook | messages, events, contacts, folders |
| Salesforce | maton.salesforce | records, query, search, composites |
| Slack | maton.slack | channels, messages, files, reactions, schedules |
| Stripe | maton.stripe | customers, charges, invoices, subscriptions, payments |
| Trello | maton.trello | boards, cards, lists, checklists, labels |
| YouTube | maton.youtube | channels, videos, playlists, comments, search |
For endpoints not yet covered by an action, use maton.api.* to reach any endpoint covered by Maton's gateway.
Reliability
Every call goes through a fetch-based client with automatic retries. The defaults are configurable on the constructor:
const maton = new Maton({
apiKey: process.env.MATON_API_KEY,
timeoutMs: 30_000, // per-request timeout, ms
maxRetries: 2, // retry attempts on transient failures
maxBackoffMs: 20_000, // cap on a single backoff sleep, ms
});Retries fire on connection errors and on 429 / 500 / 502 / 503 / 504; other 4xx/5xx surface immediately. Backoff is truncated exponential with full jitter (botocore standard mode), and honors a server-provided Retry-After header.
Errors
All failures raise a subclass of MatonError, each carrying statusCode, requestId, and the parsed body:
import { Maton, MatonError, TooManyRequestsError } from "@maton/sdk";
try {
await maton.google_mail.message.get({ messageId, connection: connectionId });
} catch (err) {
if (err instanceof TooManyRequestsError) {
console.error("slow down; retry after", err.retryAfter);
} else if (err instanceof MatonError) {
console.error(err.statusCode, err.requestId, err.body);
}
throw err;
}The hierarchy mirrors the gateway's status mapping:
| Error | HTTP status |
|---|---|
| AccessDeniedError | 401, 403 — bad/missing API key or insufficient scope |
| ResourceNotFoundError | 404 |
| TooManyRequestsError (carries retryAfter) | 429 |
| ValidationError | other 4xx (incl. 412 when an action needs a connection) |
| InternalServerError | 5xx or unexpected upstream response |
| APIConnectionError | transport failure / timeout (original via cause) |
A handful of apps wrap their vendor-specific error envelopes (e.g. a GraphQL errors array or a Slack ok: false payload) in a dedicated subclass, so you can catch them by app while still falling back to MatonError:
| Error | App |
|---|---|
| GitHubError | GitHub GraphQL/API errors |
| GoogleDriveError | Google Drive API errors |
| LinearError | Linear GraphQL/API errors |
| SlackError | Slack API errors |
| StripeError | Stripe API errors |
| YouTubeError | YouTube API errors |
Development
npm install
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm run test # vitest
npm run build # tsup → dist/ (ESM + CJS + .d.ts)
npm run smoke # tsx --watch scripts/smoke.ts (live, hits the real gateway)npm run smoke runs scripts/smoke.ts, a live harness that exercises every
app's read paths against the real gateway — the TypeScript analog of the Python
SDK's smoke_all_apps notebook. Copy .env.example to .env.local, set
MATON_API_KEY, then uncomment the app block(s) you want to run. Destructive
calls (sends, deletes) stay commented out by default.
