Optionalsource?: stringCanonical ID for the item in an external system. When set, uniquely identifies the link for the user. This performs an upsert.
Optionalsources?: string[]Canonical identifiers for this item. Any element shared with another
link's sources bundles the two links into the same thread. Used for
cross-connector bundling — e.g. a meeting-notes connector setting
["granola:<id>", "icaluid:<uid>"] to attach onto a calendar event
thread that includes icaluid:<uid> in its own sources.
Optionalfacets?: ThreadFacetsHeuristic facets describing this item (format / automation / reach),
used as internal classifier signal. Omit a dimension (or set null) when
no heuristic is confident. See @plotday/twister/facets.
Optionalsignals?: LinkSignalsRaw signals this item was derived from (email headers, provider
categories). The platform derives classification from these. Prefer this
over facets: emitting signals lets classification improve without a
connector redeploy. See @plotday/twister/signals.
When both are set, signals wins.
Optionalauthor?: NewActor | nullThe person who created this item in the external system.
Connectors MUST set this to the real external author (the message
sender, the card/issue creator, the document owner, the meeting owner —
whatever your API exposes). If you leave it unset, the item is credited
to the connector itself, so the thread surfaces as authored by the
integration's name ("Trello", "Slack") instead of a person. That is
almost always wrong and is the single most common connector attribution
bug — set the author on the link AND on its primary/description note AND
on every comment/message note (see the Authorship section of the
connector guide). Use Note.authoredBySelf for the connection owner's
own messages when the provider gives no usable sender id.
Set an explicit null only when the item genuinely has no human author
(e.g. a system-generated record) — that documents the intent and
suppresses the development-time "missing author" warning.
Twists may leave this unset: an item a twist creates is authored by the twist, which is the intended default for twist-generated content.
Optionalassignee?: NewActor | nullThe person assigned to the item.
Optionalaccess?: ThreadAccessLevelThread access level: "public", "members" (default), or "private". When "private", thread visibility is limited to the creator and contacts in accessContacts.
OptionalaccessContacts?: NewContact[]Contacts who can see a private thread. Pass email-based NewContact objects; they are resolved to contact IDs by the API. If omitted for a private thread, defaults to the connection owner.
Optionalunread?: booleanWhether the thread should be marked as unread for users.
Optionalarchived?: booleanWhether the thread is archived.
Optionaltodo?: booleanMark the thread as the connection owner's to-do at create time.
integrations.setThreadToDo() round-trip needed.Use for messaging-style "saved for later" flags (e.g. a starred Slack
thread). This is the first-class replacement for overloading a
statuses[] entry with active: true.
OptionaltodoDate?: Date | stringThe to-do date used when todo is true. Defaults to the "Now"
sentinel (today's bucket) when omitted. Ignored when todo is not true.
Optionalfocus?: Pick<Focus, "id">Explicit focus (disables automatic focus matching). Only used when the link creates a new thread. When omitted, the server classifies the thread using the user's focus rules.
Optionalpriority?: numberPrimary-link ranking for this canonical link (default 0). Set higher on the connection that "owns" the external item (e.g. the calendar that owns an event vs a subscribed copy) so clients display it as the primary.
OptionalautoThread?: AutoThreadConfig | nullOpt this message into the platform's sequential auto-threading. When a connection has auto-threading enabled, the runtime decides — once, globally, at ingest — whether this message starts a new thread or folds (as a note) into the thread of the conversation it continues. Set it on every message of a conversational surface (a chat channel, a DM); the runtime keys the sequential chain on AutoThreadConfig.key.
Marking a link is a no-op unless the connection opted in, so connectors can set it unconditionally on eligible links. Leave undefined/null for non-conversational items (issues, events, files). See Connector.autoThreading.
OptionalupdateOnly?: booleanApply this link only as an UPDATE to a thread that already exists for its
source/sources; never CREATE a new thread. When no matching thread is
found, saveLink()/saveLinks() skip the link entirely and return
null for it.
Use for signals that are only meaningful as an update to an item the user already has — most notably a calendar cancellation, which should annotate an event that was imported, never materialize a standalone "cancelled" thread for an occurrence the user never saw. Leave undefined/false for normal links, which create the thread when absent.
Type for creating new links.
Links are created by sources to represent external entities. Requires a source identifier for dedup/upsert.