Official Python SDK for Maton — connect and automate 150+ apps.
Project description
maton-ai
Official Python SDK for Maton — connect and automate 150+ apps (Gmail, Slack, GitHub, Notion, HubSpot, Airtable, and more) from Python.
Status: Alpha. Pre-1.0 releases may break action method shapes and error types between minor versions. Pin exactly (
maton-ai==0.1.0) until 1.0.
Install
From PyPI (once published):
pip install maton-ai
From GitHub (alpha / preview):
pip install "maton-ai @ git+https://github.com/maton-ai/maton-py@main"
Requires Python 3.10+.
Quickstart
import os
from maton_ai import Maton
maton = Maton(api_key=os.environ["MATON_API_KEY"])
conn = maton.connection.create(app="gmail")
connection_id = conn["id"]
gmail = maton.google_mail(connection=connection_id)
messages = gmail.message.list(q="is:unread", max_results=10)
gmail.message.send(to="alice@example.com", subject="hi", body="hello")
The same pattern works for every supported app:
slack = maton.slack(connection=slack_conn_id)
slack.message.send(channel="#general", text="deploy finished ✅")
gh = maton.github(connection=gh_conn_id)
gh.issue.create(repo="maton-ai/maton-py", title="bug: ...", body="...")
notion = maton.notion(connection=notion_conn_id)
notion.data_source.query(data_source_id="...", filter={"property": "Status", "status": {"equals": "Done"}})
hubspot = maton.hubspot(connection=hubspot_conn_id)
hubspot.contact.list(limit=25)
There are three places to select a connection, in order of precedence (per-call beats accessor beats constructor):
maton = Maton(api_key=..., connection=connection_id)
gmail = maton.google_mail(connection=connection_id)
gmail.message.list(q="is:unread")
maton.google_mail.message.list(q="is:unread", connection=connection_id)
Generic passthrough:
maton.api.post(
"google-mail",
"/gmail/v1/users/me/messages/send",
json={"raw": "..."},
connection=connection_id,
)
Triggers
Triggers register an event source (e.g. GitHub pull_request.opened) and fan
matching events out to webhook destinations. Manage them through
maton.trigger, with maton.trigger.destination and maton.trigger.event
sub-resources:
trigger = maton.trigger.create(
source="github",
event_type="pull_request.opened",
connection_id=gh_conn_id,
parameters={"repo": "maton-ai/cli"},
destinations=[{"url": "https://example.com/hook"}],
)
trigger_id = trigger["trigger"]["trigger_id"]
maton.trigger.list(source="github", status="ENABLED")
maton.trigger.update(trigger_id, status="DISABLED")
dst = maton.trigger.destination.create(trigger_id, url="https://example.com/hook")
maton.trigger.destination.rotate_secret(trigger_id, dst["destination"]["destination_id"])
events = maton.trigger.event.list(trigger_id, limit=20)
maton.trigger.event.replay(trigger_id, events["events"][0]["event_id"])
for event in maton.trigger.event.watch(trigger_id):
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 |
| Trello | maton.trello |
boards, cards, lists, checklists, labels |
| YouTube | maton.youtube |
channels, videos, playlists, comments, search |
Reliability
Every call goes through an httpx-based client with automatic retries. The
defaults are configurable on the constructor:
maton = Maton(
api_key=...,
timeout=30.0, # per-request timeout, seconds
max_retries=2, # retry attempts on transient failures
max_backoff=20.0, # cap on a single backoff sleep, seconds
)
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 status_code,
request_id, and the parsed body:
| Exception | When |
|---|---|
AccessDeniedError |
401/403 — bad/missing API key or insufficient scope |
ResourceNotFoundError |
404 |
TooManyRequestsError |
429 — also exposes .retry_after |
ValidationError |
other 4xx (incl. 412 when an action needs a connection) |
InternalServerError |
5xx or unexpected upstream response |
APIConnectionError |
network/transport failure (couldn't reach the gateway) |
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:
| Exception | App |
|---|---|
GitHubError |
GitHub GraphQL/API errors |
GoogleDriveError |
Google Drive API errors |
LinearError |
Linear GraphQL/API errors |
SlackError |
Slack API errors |
StripeError |
Stripe API errors |
from maton_ai import MatonError, TooManyRequestsError
try:
maton.google_mail.message.list(q="is:unread", connection=connection_id)
except TooManyRequestsError as exc:
print("slow down; retry after", exc.retry_after)
except MatonError as exc:
print(exc.status_code, exc.request_id, exc.body)
Development
This repo uses Hatch.
hatch env create # set up the default env
hatch run lint # ruff check + format check
hatch run fmt # ruff format + autofix
hatch run type # mypy --strict on src/maton_ai
hatch run test # pytest
hatch run test:test # full Python 3.10/3.11/3.12 matrix
hatch run clean # remove __pycache__ / *.pyc
Linting and formatting use Ruff (line length 120) — it covers pyflakes, isort, bugbear, pyupgrade, and unused-import/variable removal in one tool.
Install the pre-commit hooks once after setting up your env so Ruff and basic hygiene checks run on every commit:
pip install -e ".[dev]" # or: hatch shell
pre-commit install
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file maton_ai-0.1.0.tar.gz.
File metadata
- Download URL: maton_ai-0.1.0.tar.gz
- Upload date:
- Size: 100.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ab65511312ae561f57963f639d6381c959ef3b3506f644a780e4f7e58fca21d
|
|
| MD5 |
f9e7bf67647d44e670bd6269cb59e540
|
|
| BLAKE2b-256 |
3656b643d6b13df7d6c81c3dc36744b0070ff2d9811dc69c97e1e1edf9f3947a
|
Provenance
The following attestation bundles were made for maton_ai-0.1.0.tar.gz:
Publisher:
release-pypi.yml on maton-ai/maton-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
maton_ai-0.1.0.tar.gz -
Subject digest:
5ab65511312ae561f57963f639d6381c959ef3b3506f644a780e4f7e58fca21d - Sigstore transparency entry: 2133691072
- Sigstore integration time:
-
Permalink:
maton-ai/maton-py@40c9e8a7a09e4d93edc793ae853cf237a12f42c7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/maton-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@40c9e8a7a09e4d93edc793ae853cf237a12f42c7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file maton_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: maton_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 122.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e1eaa0b7de44b6359d57244c93dc7059ea703c346b94f888e2982326bae80d9
|
|
| MD5 |
2421c7afa510c9ad7a83811855bab8c3
|
|
| BLAKE2b-256 |
1e8891b8dae1f128b728199f7f1d9b7235eb991e6c73beecd0f5869eff7872ef
|
Provenance
The following attestation bundles were made for maton_ai-0.1.0-py3-none-any.whl:
Publisher:
release-pypi.yml on maton-ai/maton-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
maton_ai-0.1.0-py3-none-any.whl -
Subject digest:
0e1eaa0b7de44b6359d57244c93dc7059ea703c346b94f888e2982326bae80d9 - Sigstore transparency entry: 2133691087
- Sigstore integration time:
-
Permalink:
maton-ai/maton-py@40c9e8a7a09e4d93edc793ae853cf237a12f42c7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/maton-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@40c9e8a7a09e4d93edc793ae853cf237a12f42c7 -
Trigger Event:
push
-
Statement type: