Connectors are how the integration hub talks to external systems, and they come in two tiers with one rule of thumb: if a partner is "JSON over HTTPS with standard auth", it is a manifest connector — a reviewed JSON descriptor, no code; if it needs a real driver, SDK or non-HTTP transport, it is a compiled connector. Both tiers implement the same contract, are dispatched identically by the integration executor, and appear in the same server-authoritative catalog that drives the connection picker and its configuration forms — so which tier a connector belongs to is invisible to the administrator using it.
The two tiers
| Compiled connector | Manifest connector | |
|---|---|---|
| Authored as | Code, by the platform team | A reviewed JSON descriptor |
| One per | Transport or SDK that needs real code | REST partner (HTTP + auth + mapping) |
| Interpreted by | Itself | One shared manifest interpreter |
| Examples | Generic REST (http.rest), Salesforce (salesforce.rest), message-bus queues (azure.servicebus), SFTP (sftp) | HubSpot (hubspot.crm), Zendesk (zendesk.support), Shopify (shopify.admin) |
A connector's capabilities — read, write, bulk write, connection test, pagination — are inferred from what it implements, never declared separately, so the catalog cannot drift from actual behavior. Compiled connectors exist for the things templated HTTP cannot express: databases, message brokers, object stores, file protocols, and HTTP APIs outside the manifest model (form-encoded bodies, SOAP, gRPC).
The manifest contract
A manifest describes a REST partner declaratively — base URL, auth scheme, how to read, how to write, how to probe the connection, and which configuration fields to ask the administrator for:
{
"manifestVersion": "1",
"type": "example.partner",
"displayName": "Example Partner",
"description": "…",
"docsUrl": "https://…",
"baseUrl": "https://api.example.com",
"auth": { "scheme": "bearer", "token": "${secret:exampleToken}" },
"read": { "method": "GET", "path": "/v1/items", "query": { }, "itemsPath": "items" },
"write": { "method": "POST", "path": "/v1/items", "headers": { }, "body": { } },
"test": { "method": "GET", "path": "/v1/ping", "okBelow": 500 },
"inputs": [
{ "path": "objectType", "label": "Object type", "kind": "select", "required": true, "options": [ ] }
]
}
| Field | Notes |
|---|---|
type | The stable, lower-kebab connector type — the catalog key |
baseUrl | Absolute HTTPS URL; may contain ${config:…} tokens for per-tenant hosts (for example a per-organization subdomain) |
auth.scheme | none, bearer (with token), basic (with username/password), or apiKey (with header/value); every value is templatable |
read.itemsPath | Dotted path selecting the record collection inside the response; when it resolves, the records are handed to the flow — otherwise the raw status/body envelope is |
write.body | The body template. A string leaf whose entire value is one ${input…} or ${config…} token is replaced by the resolved JSON value with its type preserved; omit body to send the step input as-is |
test.okBelow | Status codes below this count as a successful probe (default 500 — so auth failures still surface as failures) |
inputs[] | Declared configuration fields, projected into the typed connection form automatically — text, number, boolean, select and secret-reference kinds |
Template tokens
Three token families are resolved at execution time:
| Token | Resolves to |
|---|---|
${secret:name} | A stored partner secret — resolved by the executor, never persisted in flow configuration |
${config:a.b} | A value from the merged connection and step configuration; a secret reference stored inside a config value resolves transparently |
${input:a.b} | A value from the step's input record |
Because a whole-string token preserves the resolved value's JSON type, manifests can write numbers as numbers and objects as objects — not everything becomes a string.
What a manifest gets for free
Each manifest registers as a first-class connector: its own entry in the catalog, a typed configuration form generated from inputs, secret handling, and the platform's shared resilience pipeline — retries, per-host circuit breaking and timeouts — identical to what the compiled connectors use. No product UI changes are involved; the connection picker and forms are catalog-driven.
Current limitations
The manifest engine currently reads a single page per call (no declarative pagination), writes single records (no bulk block), supports static bearer/basic/apiKey auth (no OAuth token exchange), and sends JSON bodies (no form-encoded). Partners needing any of those either use the generic http.rest connector, which paginates and takes caller-supplied headers, or a compiled connector.
How new connectors get added
Manifests are curated: they are reviewed and shipped by xMatix, carrying the same trust as compiled code — a manifest can point HTTP anywhere, so review is a security control, not a formality. If you need a REST partner that is not in the catalog, the practical paths today are, in order: configure the partner over the generic http.rest connector yourself; or request the partner from xMatix — a clean REST partner is typically a small manifest, which is why the catalog can grow quickly. Tenant-authored manifests — writing your own connector descriptor inside the product — are planned behind appropriate guardrails (egress allow-listing, authoring permissions) but are not available yet.
Common questions
When should I use http.rest instead of waiting for a manifest?
When you need the partner now and its API is reachable with static headers. http.rest is the general-purpose escape hatch: it reads, writes, paginates and tests against any HTTP endpoint with caller-supplied configuration. A dedicated manifest earns its place by packaging the partner's specifics — auth shape, response unwrapping, a friendly config form — so administrators configure "Zendesk" rather than "HTTP".
How are partner credentials protected?
Secrets are stored in the platform's secret store and referenced from configuration as ${secret:name} tokens; the executor resolves them at call time and raw values never persist in flow or connection configuration. The connection form's secret fields store references, not values — an administrator can rotate a secret without touching the flows that use it.
Can a connector's catalog entry claim capabilities it doesn't have?
No — capabilities are inferred from what the connector actually implements rather than declared in metadata, so a connector that cannot bulk-write never advertises bulk write. When the connection picker shows a capability, the executor can genuinely dispatch it.
