The Connector Contract¶
This document describes the output of connectors and the input to connectors. The output is the dataset that the connector writes to when synchronizing entities from the system. The input is the desired state of the system and the input to the connector to make it so.
Output of the connector¶
The dataset must use the following naming convention: SYSTEM-DATATYPE-collect, e.g. foo-person-collect.
Connector should expose the data as close to the original API as possible. If any properties are added by the connector that are not in the API, they should be prefixed with sesam_, e.g. sesam_saleId so that we know which data has been added by the connector.
Properties¶
Property |
Datatype |
Description |
Required |
|---|---|---|---|
|
Opaque |
The value of the |
No |
|
Datetime |
This is a timestamp that tells when the entity was last modified in the system. The property is optional, but it is best to collect this information from the system or as close to the system as possible. |
No |
Example: existing entity in system¶
{
"_id": "0",
"id": 0,
"key": "a",
"value": 10,
"$last-modified": "~t2023-01-30T12:00:01Z"
}
Example: an entity that has previously been inserted by Sesam¶
{
"_id": "0",
"id": 0,
"key": "a",
"value": 10,
"$origin": "~:bar-person:123",
"$last-modified": "~t2023-01-30T12:00:01Z"
}
The input to the connector¶
The dataset must use the following naming convention: SYSTEM-DATATYPE-transform, e.g. foo-person-transform.
The dataset represents the desired state of the target system. The connector will make sure that the system reflects the desired state. Entities in the dataset should have the same structure as the output of the connector. Namespaces have been removed from the properties, but not from the _id property value. The properties have the same names, data types and structure as in the collect dataset.
If the source entity consists of one or more entities from the system, then it must be split into an entity for each of the entities. The _id property must use the system specific enriched _id, e.g. if foo-person:123 (it must be namespaced) and foo:person:124 has been merged then one entity must be output for each of them.
If the source entity consists of no entities from the target system, then then output one entity. The _id property must be copied as-is from the source entity. This _id that will be treated as the origin of the inserted entity.
Properties¶
Property |
Datatype |
Description |
Required |
|---|---|---|---|
|
List<NI> |
The property must contain |
Required during insert. Optional for updated and deletes. |
|
Dict<String,Any> |
The entity must contain the |
Required for updates and deletes. Disallowed for insert. |
|
List<String> |
This property enumerates the properties that are considered for |
Required for updates and deletes. Disallowed for insert. |
|
Boolean |
If set to true then it is not a real delete, but rather the entity got a new |
Optional for deletes. Disallowed for update and insert. |
|
Opaque |
The share pipe will just pass through the |
Optional if the entity originated in this particular system. |
Example: insert¶
This entity does not have a system primary key, i.e. the id property, and will result in an insert into the system.
{
"_id": "bar-person:1",
"_deleted": false,
"$ids": [
"~:bar-person:1"
],
"key": "a",
"value": 10
}
Example: $replaced=true¶
The entity with this _id has been merged into another entity. The $replaced property and the _delete property was created by an upstream merge source and this must be communicated downstream to the dataset.
{
"_id": "bar-person:1",
"_deleted": true,
"$replaced": true
}
Example: update¶
The properties in $based_on is different from the properties on the entity, so the entity will be updated in the system accordingly.
{
"_id": "foo-person:0",
"_deleted": false,
"$based_on": [
"id": 0,
"key": "a",
"value": 10
],
"id": 0,
"key": "a",
"value": 20
}
Example: delete¶
The entity has been marked as deleted and will therefore be deleted in the system.
{
"_id": "foo-person:0",
"_deleted": true
}
Injected variables¶
Any strings on the form {{@ foo @}} in the non-expanded connector configuration represent Jinja variables that are
injected into the configuration by a tool such as sesam-py.
With some exceptions, most of the variables that support this must be
listed in a connector’s manifest to be made available. Some of these variables are always available and do not need to
be specified anywhere, such as datatype.
The table below lists the supported variables.
Overview¶
Variable |
Type |
|---|---|
String |
|
String |
|
String |
|
String |
|
String |
|
Boolean |
|
String |
|
String |
|
String |
|
String |
Authentication-specific variables¶
The values for these variables are retrieved from the output of the Consumer portal for a given tenant.
The account_id Jinja variable can be used to inject the ID of the account that a tenant has connected to a system
with in the Consumer portal.
The connected_ts Jinja variable injects the timestamp for when an entity type/datatype has been enabled in the
Consumer portal.
The is_fullsync Jinja variable (EXPERIMENTAL) injects a boolean depending on whether a datatype has set
fullsync to true or false by the user.
System-specific variables¶
The system Jinja variable is always available and injects the name of the system (for example “hubspot”, “wave” …)
Datatype-specific variables¶
The datatype Jinja variable is available for any configuration that belongs to a datatype and injects the name
of the datatype. Datatypes in the manifest can also be set to use specific properties:
The parent Jinja variable is replaced with the value of the parent property set for a datatype.
Properties from connector configuration¶
Properties from a provided connector configuration can also be injected.
The token_url Jinja variable injects the URL of an endpoint that grants an OAuth2 access token.
The base_url Jinja variable injects the base URL of the API for the system.
Service API access¶
Setting requires_service_api_access to true in the manifest signals that any occurrences of the service_url
Jinja variable should be replaced with “$ENV(service_url)”, and a JWT granting access to the service API is added as a
secret to the connector’s system. The secret can then be used in the config with $SECRET(service_jwt).
Webhooks¶
Setting use_webhook_secret to true in the manifest signals that a secret intended for validating incoming
requests to a receiver endpoint should be added to the system. The write permissions on all receiver endpoints that end
with -event in this connector will also be set to group:Anonymous. This is meant to be used with the validation_expression in the
HTTP endpoint source.
Setting <connector>_webhook_dataset under additional_parameters in the manifest signals that any occurrences of
the <connector>_webhook_dataset Jinja variable should be replaced with “$ENV(<connector>_webhook_dataset)”.
Other parameters¶
Any parameter and its value can be specified under the parameters section of a datatype in the manifest, replacing
any occurrence of that parameter in the configuration with the given value. For example, we can have a datatype
contact that has this configuration in the manifest:
{
"datatypes": {
"contact": {
...
"parameters": {
"foo": "bar"
}
}
}
}
This indicates that all occurrences of {{@ foo @}} in the contact template should be replaced with bar.
Boolean values are also supported.
Injected configuration¶
In addition to injecting Jinja-type variables directly into the configuration (see the above section), certain properties in the expanded pipe configurations can be set with the connector configuration and the pipe metadata.
Overview¶
Property |
Type |
|---|---|
String |
|
String |
|
Boolean |
Pump properties¶
Setting metadata.supports_since on a pipe template will modify the pump’s schedule_interval (if it is a collect
pipe). By default, collect pipes run at a schedule of every 300 seconds. If metadata.supports_since is set to
true, the pump will be set to run every 10 seconds instead.
Setting datatypes.<datatype>.sync_frequency to "slow" on a given datatype in the manifest will set the pump of
the collect pipe to run only once per day at midnight.
Setting datatypes.<datatype>.sync_frequency to "weekly" on a given datatype in the manifest will set the pump of
the collect pipe to run only at 00:00 on Mondays.
Setting datatypes.<datatype>.webhook to true on a given datatype in the manifest signals that the datatype
supports webhooks, and the collect pipe will be set to run on a slower schedule (default is once per hour).
A custom value for the schedule_interval on the input pipe for a given datatype can be set under
datatypes.<datatype>.schedule_interval in the manifest. This takes precedence over all the above options.
Injected secrets¶
Some variables are injected as secrets. Those variables typically contain sensitive information, like api keys and oauth2 tokens.
Api key¶
For connectors that use api_key authentication, the key will be injected as a system secret called api_key.
Oauth2¶
For connectors that use oauth2 authentication, the following secrets will be injected as system secrets:
Property |
Description |
Type |
|---|---|---|
|
The initial oauth2 access token obtained during onboarding. |
String |
|
The client id as provided in the connector configuration. |
String |
|
The client secret as provided in the connector configuration. |
String |
|
The initial oauth2 refresh token obtained during onboarding. |
String |
Tripletex authentication¶
Tripletex uses a custom style of authentication, and the following secrets will be injected as system secrets:
Property |
Description |
Type |
|---|---|---|
|
The consumer token as provided in the connector configuration. |
String |
|
The employee token as obtained during the onboarding. |
String |
SuperOffice authentication¶
SuperOffice uses a variant of Oauth2 authentication, and their keep alive key will be injected as so_ticket in addition to the regular oauth secrets.