Skip to Content
PlugSync documentation preview build
ReferenceConfig V3`entities[]` reference

entities[] reference

An entity is a logical record type (company, contact, deal, …) plus one or more schemas that describe how that record looks in each system the connector touches. The HubSpot schema (schemas.hubspot) is by far the most common.

See connector.md for the surrounding ConnectorConfigV3 envelope, and simple-vs-federated.md for when to use a single hubspot schema versus a multi-schema federated layout.

Shape at a glance

A minimal simple-mode entity (1 source, HubSpot target):

{ "name": "company", "schemas": { "hubspot": { "object_type": "companies", "identity": {"strategy": "match_or_create", "property": "hs_tax_id"}, "identity_source_path": "$.payload.id", "identity_response_path": "$.id", "field_mappings": [ {"source": "$.payload.name", "target": "name"}, {"source": "$.payload.vat_number", "target": "hs_tax_id"} ] } } }

A federated entity adds canonical and source-specific schemas alongside hubspot; see simple-vs-federated.md.

EntityV3 fields

FieldTypeRequiredNotes
namestringyesUnique within the config. Used by flow steps as entity.
schemasdict[str, EntitySchemaSpec]yesKeyed by system name (hubspot, canonical, <source>).

The schemas dict accepts arbitrary keys, but two are behaviorally special:

  • hubspot - recognized by HubSpot-targeting actions like find / upsert (the runtime raises PermanentError if find is invoked with target != "hubspot").
  • canonical - the conventional intermediate shape that transform steps write into (see simple-vs-federated.md).

Other keys are used for non-HubSpot targets via the post action.

Unlike EntitySchemaSpec, IdentityConfig, and FieldMapping, EntityV3 does not declare extra="allow". Passing unknown fields (for example a literal mode key) at the entity level will fail validation.

EntitySchemaSpec fields

FieldTypeRequiredNotes
object_typestring or nullnoThe target system’s object identifier (e.g., "companies", "0-2").
identityIdentityConfig or nullnoHow to identify existing records. See “Identity” below.
identity_source_pathstring (JSONPath)noJSONPath into the inbound payload that yields the external id.
identity_response_pathstring (JSONPath)noJSONPath into the target’s response that yields the new external id.
credential_namestring or nullnoName of the credential to use for this schema. Optional - outbound schemas can run without auth. If declared, the publish-time validator checks the credential exists in your org.
field_mappingslist[FieldMapping]noDefaults to []. See “Field mappings” below.

EntitySchemaSpec declares extra="allow"; unknown keys do not raise but are ignored by the runtime.

Identity

{"identity": {"strategy": "match_or_create", "property": "hs_tax_id"}}

IdentityConfig.strategy is one of three values (verified against (internal plugsync tooling - see the source repo)):

StrategyBehavior
match_or_createLook up the local mapping first. If absent and the search property is set AND present in the payload, search the target by that property. Reuse on hit, otherwise create.
external_id_onlyLook up the local mapping only. If a mapping exists, reuse it; otherwise the resolver returns create with no remote search.
by_emailSearch the target directly by an email property (defaults to email) drawn from the inbound payload. Unlike match_or_create and external_id_only, by_email does not check the local mapping. On miss the resolver returns action=not_found rather than action=create.

IdentityConfig declares extra="allow", so per-strategy parameters (for example property for match_or_create) ride along on the same object. The resolver reads the search property out-of-band, so this page does not prescribe an exhaustive list; consult the engine source for the live set.

Publish-time identity validator

When an entity schema declares an identity config and the schema key is not hubspot, the publish validator (_validate_identity_config in (internal plugsync tooling - see the source repo)) requires identity_response_path to be set. Without it the runtime cannot writeback the mapping after a successful create, so the next event for the same record would duplicate. Missing the path blocks publish with a ValidationFailedError (HTTP 422), not a draft-save error.

Field mappings

{"source": "$.payload.vat_number", "target": "hs_tax_id"}
{"source": "$.payload.created_at", "target": "created_at", "transform": "iso_to_unix_ms"}

FieldMapping fields:

FieldTypeRequiredNotes
sourcestring (JSONPath)yesRead path. Common roots: $.payload.*, $.canonical.*.
targetstringyesTarget property name in the schema’s object_type.
transformstring or nullnoName of a registered transform. See “Transforms” below.
argsdict or nullnoArguments passed to the named transform.

FieldMapping declares extra="allow"; unknown keys are ignored.

JSONPath conventions

The field-mapping resolver (_resolve_value in (internal plugsync tooling - see the source repo)) recognizes exactly these roots:

  • $.payload.* - the raw inbound event body (inbound flows).
  • $.canonical.* - the intermediate canonical shape (federated mode).
  • $<step_id> (no dot) - the full output of a prior step in the same flow.
  • $.<step_id>.* - a nested field on a prior step’s output.

Anything else (for example $.identity.* or $.event) returns None - those are not valid field-mapping roots.

Transforms

The transform registry comes from the TransformNode union in (internal plugsync tooling - see the source repo). Four variants are supported:

VariantPurpose
TransformNodePathRead a JSONPath, optionally with default and transform / args.
TransformNodeTemplateString template ("{first} {last}"), with safe-brace validation.
TransformNodeConstInline constant value.
TransformNodeConcatConcatenate a list of values.

Named transforms (the strings passed in the mapping’s transform field) are specific to each project; consult the engine source or your connector’s configured transforms to enumerate the live set.

The publish-time transform validator (_validate_transforms in publish_service.py) requires the transform name on every FieldMapping to be either (a) a name in the engine’s built-in transform registry (supported_transform_names()), or (b) a name declared under config.transforms (the config-level transform registry, see roadmap). Unknown names fail at publish with ValidationFailedError, not at draft save.

See flows.md for how field_mappings are consumed inside upsert / create / update steps, and how transform steps populate $.canonical.* from $.payload.* in federated mode.

Last updated on