Connectors and apps
Open in
A connector says how a product talks to one outside system. An app is outside software a Customer lets in, under scopes it consents to.
The connection is a grant the admin revokes at any time. Filled: what the admin sees.
Connectors, one per outside system
A connector is the definition. An Integration is one Customer's connection through it.
Connectors come from the platform's catalog, from your own file, or from another builder as an installed extension, checked like one.
| Family | What a connector declares, and the platform does |
|---|---|
| Auth | The system's OAuth or key flow; tokens kept as secrets in the Customer's own Namespace, refreshed before they expire, never shown |
| Objects | Each of the system's objects mapped to a Noun of the file, such as accounts to a Noun of customers, and each field by map |
| Sync modes | read in, write back, both, or events the system sends, verified and written as Events before anything runs |
| Cursor and backfill | Where the last sync stopped; a first sync backfills from a point in time, then reads changes only |
| Conflicts | Who wins a field both sides changed: system, product, newest, or ask, which opens a review; every value keeps its Provenance |
| Deletes | What a delete on the other side does here: archive, delete or ignore |
| Rate limits | The system's own limits respected per Customer, with backoff, so one Customer's sync never slows another's |
| Field maps per Customer | A Customer's admin maps its own custom fields to fields its extension adds, without a deploy of yours |
| Health and resync | Each connection's state, lag, errors and counts, and Integration.resync for one object or everything since a time |
Apps, outside software inside a Customer's org
An app acts as its own principal, always for one Customer org, through the same gate as every call.
| Family | What it does |
|---|---|
| Registration | A developer registers an app on the product: its name, redirect addresses, Watches and the scopes it asks for |
| Scopes from Verbs | Each scope is a set of Verbs and the Role they act under, such as deals: or Deal.win; an app never gets more than the admin who installs it holds |
| Install consent | A Customer's admin installs an app for its org, sees each scope in words, and can narrow them |
| Review | apps.review says whether you review an app before any Customer but its maker's may install it |
| Caps per app | A call limit per app and per install, apart from the Customer's own, so one app cannot spend the Customer's limits |
| What an app sees | Its installs, its Watches' deliveries, its own calls, and refusals with cures like any caller |
Example
Each Customer's own CRM, synced both ways for accounts and opportunities, with the newest change winning; and apps you review first.
import { define } from 'apis.dev'
/** Deals for each Customer, kicked off when won. */
export default define({
name: 'pipeline', domain: 'pipeline.apis.dev',
sources: {
crm: {
system: 'crm', scope: 'customer', sync: 'both',
objects: { accounts: 'Company', opportunities: 'Deal' },
conflict: 'newest', deletes: 'archive',
},
},
Company: {
name: { type: 'string', from: 'crm', map: 'name' },
domain: { type: 'url!#', from: 'crm', map: 'website' },
deals: '<-Deal.company',
},
Deal: {
title: 'string', amount: 'decimal(12, 2)', company: '->Company.deals',
stage: { open: [], qualify: 'opened', win: 'qualified', lose: ['opened', 'qualified'] },
},
apps: { review: 'you', calls: { day: 10000 } },
offer: { Team: { month: 49, seats: 5, seat: 9 }, 'Deal.open': 0.001 },
})A Customer's admin reads its connection's health.
HTTP/1.1 200 OK
Content-Type: application/ json
X-Cost: price= 0, currency= "USD"
X-Request-Id: req_c41e7b02d98a3f65e0b9
{
"id": "int_crm",
"state": "syncing",
"sync": "both",
"cursor": "2026-10-27T08: 55: 00Z",
"objects": {
"accounts": { "read": 1240, "written": 18, "conflicts": 2 },
"opportunities": { "read": 310, "written": 44, "conflicts": 0 }
},
"lag": "4m",
"limit": { "used": 0.31, "resets": "2026-10-27T09: 00: 00Z" }
}That is GET /integrations/, getIntegration over MCP and pipeline integrations get crm in the CLI.
Connections and apps, state by state
Every move is a Verb a Customer's admin or its agent makes, and each writes its Event.
| Thing | States | What moves it |
|---|---|---|
| A connection | offered, connecting, backfilling, syncing; or degraded, paused, disconnected, revoked | The admin's consent, the first sync, token refresh, the system's limits, Integration.pause and the admin's revoke |
| A sync run | reading, writing, done; or partial, retrying, failed | The cursor and the system's answers; a partial run says which objects it reached |
| A conflict | found, then resolved by the rule, or asked and then resolved by a person | The connector's conflict rule, or a reviewer's choice |
| A published connector | draft, checked, published, deprecated | Connector.publish; a new version is checked before it reaches any install |
| An app | registered, in_review, approved, suspended, retired | Its developer, your review on the Operator plane, and App.suspend |
| An install | consented, active, narrowed, revoked | A Customer's admin; a revoke ends every token the app holds for that org at once |
What admins, developers and agents meet
- A Customer's admin. Connect its own system from the portal or the API, map its fields, watch its health, and revoke it.
- A member. Records that stay in step with the system it works in, and a conflict it can see and settle.
- A developer. Register an app, ask for scopes in Verbs, pass review, and reach every Customer who installs it.
- An agent. Connect, map, resync and revoke by Verb, and read the same health a person reads.
Every outside system meets the product through a connector, and every outside app through scopes made of Verbs, so both pass the one gate.