Docs / Connectors
Connectors, marketplace and inbound email
How connectors are listed, installed and reviewed, the one inbound-email interface every mail connector uses, and how official connectors register themselves.
Long form: docs/connectors.md. This page is the working summary next to the code in apps/services/src/connect.
Marketplace#
GET /v1/connect/registry lists what is listed (staff see everything with installation counts). GET /v1/connect/registry/:slug is one connector for its detail page. Each entry carries the catalog fields
(category, summary, long description, icon, privacy and support links, data read and written, what it asks of the third party) plus, for organization members, viewer: may this person install, and this
organization's installation. Installing needs manage_users; it is audited as connector.installed. Staff list or unlist (PUT /registry/:slug/status), dry-run a pasted manifest
(POST /registry/validate) and see installations per connector (GET /registry/:slug/installations, organization names only).
Inbound email, any provider#
PUT /v1/connect/v1/emails/:externalId with scope messages:draft. The body is the sender, subject, new text without quoted history, attachment names, threading ids and optional parsed answers. Core matches it
in the installing organization only: the addressed reference (hint.referenceId), else an open reference whose address is the sender, else an application whose contact is the sender. Anything else answers
matched: false and nothing is stored. A match is a ConnectorDraft of kind email. Accepting records an unsigned reference response (same transaction, claim, revision and activity as a signed one,
labelled unsigned everywhere) or an internal note and timeline entry on the application, with the audit event connector_draft.accepted in the same transaction.
Status#
PUT /v1/connect/v1/status lets a connector say active or needs_attention with a message, its last sync and the mailbox address it reads. The Connectors page shows it. When a mailbox is connected, reference
requests sent afterwards use that address as Reply-To.
Registration of official connectors#
PUT /v1/connect/internal/registry/:slug with Authorization: Bearer $INTERNAL_API_KEY is used by the connectors-register job and by pnpm dev:local. It is off (404) unless the key is set, refuses requests
that carry proxy forwarding headers, is blocked at the proxy, compares the key in constant time and audits connector.registered with via: internal and no secret. Status is listed only while the connector
reports it is configured.
Signing#
Scope signatures:fulfil. A connector carries core's signing requests to a provider; core stays the judge. Calls are installation scoped: another organization's request, or one that belongs to another provider, is a 404, a missing scope a 403.
All writes are idempotent. Routes under /v1/connect/v1/signature-requests:
| Call | Purpose |
|---|---|
| `GET ?state=queued | sent |
GET /:id/unsigned | The PDF to sign, as bytes. 409 not_ready until the virus scan released it. |
PUT /:id/provider { externalId } | The provider created it: queued to sent, signers pending. |
PUT /:id/events/:eventId `{ type: viewed | signed |
PUT /:id/sealed (body: PDF) | The provider's signed copy. Stored, scanned, then sealed by core's own checks. |
PUT /:id/certificate (body: PDF) | The provider's audit log, stored as a certificate document. |
POST /:id/fail { code } | The provider cannot take it: queued to failed. |
The SDK wraps these as installation.signatures.*. The official signing connector is Documenso.