SaaS Sync (Connectors)
Connectors pull data from external services and sync it into your connected databases. This lets you query third-party data with SQL alongside your own data.
Available Connectors
Section titled “Available Connectors”| Connector | Source | Entities |
|---|---|---|
| Stripe | Stripe API | Customers, Subscriptions, Disputes, Charges, Invoices, Products, Prices, Plans, Payment Intents, plus money-movement and billing-detail entities: Balance Transactions, Payouts, Payout Balance Transactions, Refunds, Credit Notes, Customer Balance Transactions, Invoice Items, Subscription Schedules, Coupons, Promotion Codes, Checkout Sessions, Setup Intents, Early Fraud Warnings. Supports backfill and CDC webhooks (auto-provisioning via Stripe webhook endpoints; the endpoint’s events are kept in step with the flow’s enabled entities). Customer Balance Transactions walks every customer and has no incremental mode (none). |
| Close CRM | Close API | Leads, Opportunities, Activities (10+ sub-types), Contacts, Users, Custom Fields. Webhooks are automatically scoped to synced entities only. |
| Claap | Claap API | Recordings, Recording Transcripts, Workspace. Supports backfill and CDC webhooks (auto-provisioning via “Create in Claap”). Recording Transcripts (one row per recording and language: text plus speaker segments) are downloaded while Claap’s 24-hour links are valid: on every recording_added / recording_updated webhook, and on a backfill or poll, which re-checks the two days before the last sync and stops before the workspace’s daily API quota runs out. |
| Calendly | Calendly API | Organizations, Users, Groups, Event Types, Scheduled Events, Invitees, Contacts. Real-time invitee + event-type webhooks (auto-provisioned); scheduled backfill covers the rest. |
| PandaDoc | PandaDoc API | Documents, Templates, Contacts, Members. Document + template webhooks (CDC, auto-provisioned); scheduled backfill covers contacts and members. Documents are hydrated with full detail (fields, tokens, pricing, products, recipients) during backfill. |
| Wise | Wise API | Profiles, Balances, Balance Updates, Balance Statements, Transfers, Recipients, Activities. Balance Statements are the per-balance transaction ledger for every currency, pulled in 90-day windows (incremental pulls re-read the last 7 days so late-settling transactions are caught). Some profiles require strong customer authentication for statements: add an optional SCA private key (PEM, stored encrypted) whose public key is registered in Wise under Settings → API tokens → Manage public keys. CDC webhooks verified with Wise’s RSA-SHA256 public keys; “Create in Wise” subscribes the flow’s webhook URL on every synced profile (needs a token Wise lets manage webhooks: an OAuth user token or a full-access personal token; otherwise the error explains the manual setup). Balances and Profiles have no profile-level webhook event. Transfer polls only see newly created transfers; status changes arrive via webhooks. |
| PostHog | PostHog API + HogQL | Surveys, Survey Responses, Feature Flags, Experiments, Annotations — plus dynamic HogQL query entities |
| GraphQL | Any GraphQL API | Dynamic — each configured query becomes an entity |
| BigQuery | Google BigQuery | Dynamic — each configured query becomes an entity |
| REST | Any REST API | Configurable endpoints |
How It Works
Section titled “How It Works”- Configure — Add a source connection with API credentials and select which entities to sync
- Map — Choose a destination database and table naming convention
- Sync — Connectors fetch data in chunks with cursor-based pagination
- Resume — If a sync fails, it resumes from the last saved cursor (idempotent upserts)
Probing a Connection Live
Section titled “Probing a Connection Live”A connector is defined once — check, entities, read — and a flow is only one of the things that can drive a connection made with it. The live probe runs a configured source connection, with the credential Mako holds, directly against its platform: the credential check, then one bounded page of an entity, written nowhere. Use it to confirm a new key works, to see the real shape of an entity before writing a flow, or to look at a platform’s data before a flow lands it in the warehouse.
Three surfaces, one implementation, so they cannot drift on what “bounded”, “read-only” and “no credential in the result” mean:
| Surface | How |
|---|---|
| MCP (any agent, or the in-product agent) | probe_connection({ connectionId, entity?, limit?, fields?, since? }) — ids from list_connections, entity names from inspect_connection |
| CLI | mako connection probe <id|name> [--entity <name>] [--limit <n>] [--fields a,b] [--since <iso>] [--json] |
| REST | POST /api/workspaces/:wid/connections/sources/:id/probe (legacy alias: POST /api/workspaces/:wid/connectors/:id/probe) with the same body fields |
The result carries the check outcome, then entity.records, entity.schema (declared field types), entity.hasMore (further pages exist on the platform), entity.truncated (the page held more than limit) and the connector’s own log lines. Limits: at most limit records (default 20, max 200) from a single API page, and a 90-second budget for the whole probe — a connection whose connector is workspace-authored runs in a sandbox, so its first probe can take tens of seconds. Every string value of the connection’s config is scrubbed from the result, including from a vendor error that would echo the key back.
Nothing is written: no destination table, no sync cursor. The one side effect is the same one Test connection has — a workspace source connection’s last-check mark, which is what moves its connector to verified.
Building Custom Connectors
Section titled “Building Custom Connectors”See the Building Connectors guide for implementing new connectors.
Each connector extends BaseConnector and implements:
class MyConnector extends BaseConnector { // Declare available entities and their BigQuery layout hints getEntityMetadata(): EntityMetadata[];
// Fetch a chunk of data with resumable state (cursor-based) fetchEntityChunk(options: ResumableFetchOptions): Promise<FetchState>;
// Test connectivity testConnection(): Promise<ConnectionTestResult>;
// Validate configuration validateConfig(): { valid: boolean; errors: string[] };}Configuration
Section titled “Configuration”Source connections are configured per-workspace through the UI or API. Credentials are encrypted at rest using the ENCRYPTION_KEY environment variable.