Connector templates
A connector template is a provider-scoped, reusable blueprint for a single connector. It captures everything you would otherwise re-type on POST /connectors — the type or
connector model, the per-application overrides, any ad-hoc applications — under a name you can reference, so the same connector definition can be materialized at many locations
without being copied anywhere.
It is the third and innermost level of the template family. A customer template references location templates; a location template references connector templates; a connector template materializes one connector.
:::note Not the same as a connector model A connector model defines the applications a connector hosts and stays attached to the connector for its whole life — change the model and every attached connector re-materializes. A connector template defines how to create a connector in the first place, including which model to attach, and stops mattering the moment the connector exists. The two compose: most connector templates simply name a model. :::
What a connector template is (and isn't)
- It is storage plus a shape check. Unlike a location template's inline
connectorslist, a connector template is validated when saved: atypeis required unless aconnectorModelIdsupplies one, a referenced model must exist, be live, belong to the same provider, and carry a matching type. What is not checked at save time is the content ofapplicationOverridesandapplications— those are stored verbatim,{{variable}}placeholders included, and validated when the template is applied. - It is not an active resource. Saving a template creates no connector. Materialization happens on demand, either directly via
POST /connector-templates/{templateId}/applyor indirectly when a location template that references it is applied. - It is scoped to a provider.
providerIdis set on create and immutable. Authorization gates on the parent provider through theconnect-connector-templateresource type. - It is referenced by id, not copied. A location template stores
connectorTemplateIds, so editing the connector template changes what every referencing location template will materialize next time. Connectors already created from it are untouched.
Fields
| Field | Description | Example |
|---|---|---|
id | Unique ID assigned at create time | 7e1d2c3b-4a5f-4678-9012-3456789abcde |
providerId | Parent provider — set on create, immutable | 8b14d4f9-3a52-4b91-8e7c-d3e44b5c1f2a |
name | Human-readable name, unique within the provider (1–255 chars). Identifies the template itself; it isn't the created connector's name | Standard branch gateway |
connectorName | Default for the created connector's name — seeds the apply body's name, which the caller can override. Required (1–180 chars). Supports {{variable}} substitution | {{location.name}}-gw |
connectorDescription | Default for the created connector's description — seeds the apply body's description. Optional (≤1024 chars). Supports {{variable}} substitution | Managed by {{provider.name}} |
type | Type of the created connector. Required unless connectorModelId is set, in which case it is derived from the model | GATEWAY |
connectorModelId | Connector model the created connector inherits its applications from. Must belong to this template's provider | 3f2a1b0c-9d8e-4f70-a1b2-c3d4e5f60718 |
applicationOverrides | Per-application overrides applied on top of the model. Only valid when connectorModelId is set. Stored verbatim, placeholders included | see Variable substitution |
applications | Ad-hoc applications created on the connector in addition to any inherited from the model. Stored verbatim; validated at apply time | |
ownerIdentityId | Identity that owns the template | c0ffee00-1111-2222-3333-444455556666 |
createdBy, createdAt, updatedAt, deletedAt, deletedBy | Standard lifecycle fields |
Updating a template
connectorModelId, applicationOverrides and applications are omission-tolerant on both PUT and PATCH: leaving one out keeps its current value rather than clearing it,
and sending it explicitly as null clears it. That is what makes detaching a model expressible at all — and a detach requires the template to carry a type, since otherwise
nothing would be left to create a connector from.
Applying a template
A connector template can be materialized two ways.
Directly, at an existing location
GET /connector-templates/{templateId}/apply returns a preview shaped exactly like the POST body, pre-filled from the template: name/description seeded from
connectorName/connectorDescription, plus a _placeholders list naming the fields the caller fills in.
| Placeholder | Meaning | Type | Required |
|---|---|---|---|
$.locationId | Location to create the connector at | UUID | yes |
$.name | The new connector's name (seeded from connectorName) | string | yes |
$.description | The new connector's description | string | no |
That is the whole caller-editable surface. The type, connector model, application overrides and ad-hoc applications come from the template and are deliberately not part of the
payload — a one-off connector that needs to differ belongs in a location template's inline connectors blueprint instead. The location must belong to the template's provider.
Indirectly, through a location template
A location template lists connectorTemplateIds. Applying it materializes one connector per entry, in order, before its own inline connectors
blueprints. The apply body carries a matching connectorTemplates array — one entry per reference, in the same order — and the server injects each connector's locationId from
the location it just created, so the caller never supplies it.
The same connector template may be referenced more than once by a single location template, which is how you express an HA pair from one blueprint. That is also why the entries
are matched positionally rather than by id, and why the counts must line up: a body whose connectorTemplates array is a different length than the template's
connectorTemplateIds is rejected before anything is created.
Because each entry still carries its own name, two connectors materialized from the same template get distinct names — either written out by the caller, or generated, since
generator tokens like {{alpha:5}} produce a different value per entry.
Variable substitution
| Property | In-scope variable namespaces |
|---|---|
connectorName → the apply body's $.name | provider.*, customer.*, location.* |
connectorDescription → the body's $.description | provider.*, customer.*, location.* |
applicationOverrides[].appName | provider.*, customer.*, location.*, connector.* |
applicationOverrides[].addresses[].* | provider.*, customer.*, location.*, connector.* |
applications[].name, applications[].description | provider.*, customer.*, location.* |
The connector's own connectorName/connectorDescription may not reference connector.*. They are never re-rendered after the connector is created, so an unresolved
{{connector.*}} there would be permanent; it is rejected as an unknown variable when the template is saved. The applicationOverrides subtree may, because it is re-rendered when
the connector materializes its model — those placeholders are carried through the apply intact and substituted at that point, exactly as a directly created connector's overrides
are.
Substitution is strict: a placeholder referencing a variable outside the catalog fails the whole apply rather than emitting a blank or a literal {{…}}. That covers a typo, a
custom variable not defined on the resolving resource, and customer.* at a provider-direct location. See Custom variables for the .custom.* sub-spaces
each namespace carries.
When the apply fails, the error names the entry it came from. A direct apply reports $.name; a connector materialized through a location template reports
connectorTemplates[0].name; and one materialized two levels down, through a customer template, reports locations[0].connectorTemplates[0].name.
Lifecycle hooks
Customer Connect listens for resource-change events and keeps templates in sync:
- Provider deleted: every connector template under that provider is deleted in turn, driven by the
connect-providerDELETEDevent. - Connector model deleted: every connector template that inherits from the deleted model is deleted, driven by the
connect-connector-modelDELETEDevent. The model is the substance of such a template — strip the reference and what remains has no applications and, once the model-derived type goes with it, nothing valid to create. Deleting it publishes its own event, which in turn strips it from every location template that referenced it, so the chain heals itself. - Connector template deleted: its id is stripped from every location template's
connectorTemplateIdslist — every occurrence of it, since one template may reference it more than once. The location template itself is preserved, even if the list ends up empty.
These hooks are best-effort housekeeping. They don't affect connectors already materialized from the template. Until the event has been consumed, a location template may still
reference a template that was just deleted; applying in that window fails with a 404 rather than materializing a connector from a retired blueprint.
Filtering
The list endpoint accepts id / name / connectorName / connectorDescription / type / providerId / connectorModelId / ownerIdentityId / createdAt / updatedAt /
deleted. connectorModelId is a plain column match — the model reference is a first-class field here, not buried in a JSON blob as it is on a location template's inline
blueprint.