Skip to content

Connectors and apps

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.

A Customer connects its own system

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.

FamilyWhat a connector declares, and the platform does
AuthThe system's OAuth or key flow; tokens kept as secrets in the Customer's own Namespace, refreshed before they expire, never shown
ObjectsEach 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 modesread in, write back, both, or events the system sends, verified and written as Events before anything runs
Cursor and backfillWhere the last sync stopped; a first sync backfills from a point in time, then reads changes only
ConflictsWho wins a field both sides changed: system, product, newest, or ask, which opens a review; every value keeps its Provenance
DeletesWhat a delete on the other side does here: archive, delete or ignore
Rate limitsThe system's own limits respected per Customer, with backoff, so one Customer's sync never slows another's
Field maps per CustomerA Customer's admin maps its own custom fields to fields its extension adds, without a deploy of yours
Health and resyncEach 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.

FamilyWhat it does
RegistrationA developer registers an app on the product: its name, redirect addresses, Watches and the scopes it asks for
Scopes from VerbsEach scope is a set of Verbs and the Role they act under, such as deals:read or Deal.win; an app never gets more than the admin who installs it holds
Install consentA Customer's admin installs an app for its org, sees each scope in words, and can narrow them
Reviewapps.review says whether you review an app before any Customer but its maker's may install it
Caps per appA 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 seesIts 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.

definition.ts
24 lines
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.

Response
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/crm, 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.

ThingStatesWhat moves it
A connectionoffered, connecting, backfilling, syncing; or degraded, paused, disconnected, revokedThe admin's consent, the first sync, token refresh, the system's limits, Integration.pause and the admin's revoke
A sync runreading, writing, done; or partial, retrying, failedThe cursor and the system's answers; a partial run says which objects it reached
A conflictfound, then resolved by the rule, or asked and then resolved by a personThe connector's conflict rule, or a reviewer's choice
A published connectordraft, checked, published, deprecatedConnector.publish; a new version is checked before it reaches any install
An appregistered, in_review, approved, suspended, retiredIts developer, your review on the Operator plane, and App.suspend
An installconsented, active, narrowed, revokedA 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.