Creating Plot Twists
    Preparing search index...

    Type Alias NewNote

    NewNote: Partial<
        Omit<
            Note,
            | "author"
            | "thread"
            | "tags"
            | "reactions"
            | "mentions"
            | "accessContacts"
            | "recipients"
            | "id"
            | "key"
            | "reNote"
            | "tagActors",
        >,
    > & ({ id: Uuid } | { key: string } | {}) & {
        thread: Pick<Thread, "id"> | { source: string };
        author?: NewActor | null;
        authoredBySelf?: boolean;
        deferUntilThread?: boolean;
        contentType?: ContentType;
        tags?: NewTags;
        reactions?: NewReactions;
        accessContacts?: (ActorId | NewContact)[] | null;
        mentions?: NewActor[];
        unread?: boolean;
        checkForTasks?: boolean;
        reNote?: { id: Uuid } | { key: string } | null;
        link?: NewLink;
    }

    Type for creating new notes.

    Requires the thread reference, with all other fields optional. Can provide id, key, or neither for note identification:

    • id: Provide a specific UUID for the note
    • key: Provide an external identifier for upsert within the thread
    • neither: A new note with auto-generated UUID will be created

    Type Declaration

    • { id: Uuid }
    • { key: string }
    • {}
    • thread: Pick<Thread, "id"> | { source: string }

      Reference to the parent thread (required)

    • Optionalauthor?: NewActor | null

      The person who wrote this note in the external system.

      Connectors MUST set this to the note's real author (the comment author, the message sender, the description's creator). Leaving it unset credits the note to the connector itself, so it surfaces as authored by the integration's name instead of a person — the most common connector attribution bug. Prefer authoredBySelf for the connection owner's own messages (see below). Set an explicit null only for a genuinely authorless/system note (it documents the intent and suppresses the development-time "missing author" warning).

      Twists may leave this unset to author the note as the twist itself.

    • OptionalauthoredBySelf?: boolean

      Mark this note as authored by the connection owner (the person whose account the connector is syncing) — e.g. a message you sent in a chat.

      When true, the runtime attributes the note to your own contact for this connection, ignoring author. Use this instead of trying to resolve your own identity from the external service: for many providers a message you sent carries no usable sender id (and 1:1 chats omit you from the participant roster), so author cannot identify you reliably. The owner is already known from the connection, so this is deterministic and needs no extra API call. If the owner has no resolvable contact, the note falls back to author.

    • OptionaldeferUntilThread?: boolean

      Keep this note until its thread exists, instead of dropping it.

      A note addressed by { source } normally resolves immediately, and saveNote returns null when no thread carries that source — which for a connector usually means the item this note belongs to has not synced yet. Set this to have the platform hold the note and attach it as soon as a thread with that source appears, rather than making you store and retry it yourself.

      Recommended for any { source }-addressed note whose target is synced by a different product or connector and may therefore lag. Leave it unset when a miss means the note is genuinely undeliverable: null is then the signal you want, and holding the note would accumulate payloads for a thread that will never arrive.

      Held notes are dropped after a bounded retry window. Ordering is not guaranteed relative to notes that attached immediately, so set created (as connectors already should) rather than relying on arrival order.

      At most one UNKEYED held note survives per { source }: two deferred notes without a key addressed to the same still-unresolved source collapse onto a single held slot, and the second one you save silently replaces the first — it does not queue as a second note. If you may defer more than one note to the same unresolved source, give each a distinct key so they are held separately.

    • OptionalcontentType?: ContentType

      Format of the note content. Determines how the note is processed:

      • 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)
      • 'markdown': Already in markdown format (default, no conversion)
      • 'html': HTML content that will be converted to markdown
    • Optionaltags?: NewTags

      Tags to change on the thread. Use an empty array of NewActor to remove a tag. Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.

    • Optionalreactions?: NewReactions

      Emoji reactions to set on the note. Pass an empty NewActor[] to remove a reaction entirely; omit an emoji to leave it untouched.

    • OptionalaccessContacts?: (ActorId | NewContact)[] | null

      Contacts who can see this note, or null/undefined to inherit thread visibility. Accepts resolved ActorId UUIDs or email-based NewContact objects (resolved server-side). Include all participants who should see the note (sender + recipients). The note author is NOT implicitly included — add them explicitly. When set (even to []), the note is private to the listed contacts plus the creator.

    • Optionalmentions?: NewActor[]

      Twist/connector IDs to mention for dispatch routing. Does not include user contacts — use accessContacts for visibility.

    • Optionalunread?: boolean

      Whether this note should change the parent thread's read state.

      • omitted (default): no explicit read-state write. Attaching a note still marks the thread unread for every recipient except the note's author — there is no "leave read state alone" outcome. Pass an explicit false if a note should NOT create unread (e.g. a low-signal annotation, or a response that says nothing the thread doesn't already show).
      • true: mark the thread unread, except for the user who authored the note — they have necessarily seen it. Redundant with the default behavior above; pass it when you want to be explicit at the call site.
      • false: mark the thread read for the connection owner. Use when the external system reports the item as already read, so a two-way sync converges.

      A note carrying accessContacts is scoped to those contacts. Scoping marks the thread unread for every visible non-author when the note lands, whatever this field says — so true is redundant on a scoped note, and false clears it again for the connection owner.

    • OptionalcheckForTasks?: boolean

      When true, the server will use AI to detect tasks in this note's content and create separate Plot-authored reply notes for each detected task. Use for messaging connectors (email, chat) where tasks are implicit in conversation rather than explicitly structured.

    • OptionalreNote?: { id: Uuid } | { key: string } | null

      Reference to a parent note this note is a reply to.

      • { id }: reply by UUID
      • { key }: reply by key, resolved after creation (for batch ops)
      • null: explicitly not a reply
      • undefined (omitted): not a reply
    • Optionallink?: NewLink

      A link carried by this note (note-attached, NOT a thread-level canonical link). Use for augmenter content (e.g. Granola meeting notes) that should attach to an existing canonical thread without becoming its primary link. The runtime creates the link note-scoped, binds note.link_id to it, and — when thread: { source } resolves to no existing thread — find-or-creates the thread by that source so a later canonical sync can fill the primary.