> ## Documentation Index
> Fetch the complete documentation index at: https://docs.api.tamtam.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a LinkedIn content signal

> Watch LinkedIn posts about a topic, have an AI score each one against your use-cases, and collect the people who liked or commented on the relevant ones as leads.

A signal is a **search** (`keywords` in LinkedIn boolean syntax and/or `company_linkedin_ids`, combined into one search) and one to ten named **use-cases**, each with its own AI prompt: what a post must be about to fall into it. Every night the sweep searches the past week, has a cheap model score each new post against every use-case (one credit per post judged; a post already judged is never judged again unless you edit the definition), and a post is relevant when it falls into at least one use-case. Each match carries the AI's reason and whatever the use-case prompt asked to extract. The likers and commenters of relevant posts become events (one credit per person collected), stamped with the use-case names their post fell into.

**Cost per sweep is bounded by `max_posts_per_sweep` (AI calls) plus relevant posts × `max_engagers_per_post` × 2 (likers and commenters).** Both default conservatively; raise them once a signal is producing what you expect.

Read the verdicts at [List judged posts](/api-reference/linkedin-content-signals/list-linkedin-content-signal-posts) and the people at [List content signal events](/api-reference/linkedin-content-signals/list-linkedin-content-signal-events).



## OpenAPI

````yaml /reference/openapi.yaml post /v2/linkedin-content-signals
openapi: 3.1.0
info:
  title: Tamtam Public API
  version: 2.0.0
servers:
  - url: https://api.tamtam.ai/api
security: []
paths:
  /v2/linkedin-content-signals:
    post:
      tags:
        - LinkedIn Content Signals
      summary: Create a LinkedIn content signal
      description: >-
        Watch LinkedIn posts about a topic, have an AI score each one against
        your use-cases, and collect the people who liked or commented on the
        relevant ones as leads.


        A signal is a **search** (`keywords` in LinkedIn boolean syntax and/or
        `company_linkedin_ids`, combined into one search) and one to ten named
        **use-cases**, each with its own AI prompt: what a post must be about to
        fall into it. Every night the sweep searches the past week, has a cheap
        model score each new post against every use-case (one credit per post
        judged; a post already judged is never judged again unless you edit the
        definition), and a post is relevant when it falls into at least one
        use-case. Each match carries the AI's reason and whatever the use-case
        prompt asked to extract. The likers and commenters of relevant posts
        become events (one credit per person collected), stamped with the
        use-case names their post fell into.


        **Cost per sweep is bounded by `max_posts_per_sweep` (AI calls) plus
        relevant posts × `max_engagers_per_post` × 2 (likers and commenters).**
        Both default conservatively; raise them once a signal is producing what
        you expect.


        Read the verdicts at [List judged
        posts](/api-reference/linkedin-content-signals/list-linkedin-content-signal-posts)
        and the people at [List content signal
        events](/api-reference/linkedin-content-signals/list-linkedin-content-signal-events).
      operationId: create-linkedin-content-signal
      parameters:
        - description: >-
            Target account UUID. Required for staff callers; ignored for
            customer API keys.
          explode: false
          in: query
          name: account_id
          schema:
            description: >-
              Target account UUID. Required for staff callers; ignored for
              customer API keys.
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LinkedinContentSignalBody'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LinkedinContentSignalDto'
          description: OK
        default:
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorModel'
          description: Error
      security:
        - apikeyAuth: []
        - bearerAuth: []
components:
  schemas:
    LinkedinContentSignalBody:
      additionalProperties: false
      properties:
        accept_all_posts:
          description: >-
            Take every post the search returns, without the AI judge and at no
            post credit; use_cases then become optional. For a search narrow
            enough to be the relevance rule itself (a competitor's own posts,
            one precise phrase). Defaults to false.
          type: boolean
        author_profile_urls:
          description: >-
            LinkedIn profile URLs (https://www.linkedin.com/in/<name>) of people
            whose posts to search. At least one of keyword_queries,
            company_linkedin_ids or author_profile_urls is required. The
            person's encoded member ID is resolved at sweep time; a URL that
            cannot be resolved is skipped and logged, never an error.
          items:
            type: string
          type:
            - array
            - 'null'
        collection:
          description: >-
            Engagers only: which person a relevant post yields. engagers (the
            default): the people who liked or commented on it. post_authors: the
            person who wrote it, for searches where the post itself is the
            buying signal. Company-page posts are skipped. No likers/commenters
            run is made under post_authors, so max_engagers_per_post is unused.
            Rejected for the authors subject.
          enum:
            - engagers
            - post_authors
          type: string
        company_linkedin_ids:
          description: >-
            Numeric LinkedIn company IDs whose posts to search (resolve with the
            companies search first). Combined with each keyword query into one
            search.
          items:
            type: string
          type:
            - array
            - 'null'
        contacts_list_ids:
          description: >-
            Contacts lists whose members an authors signal watches. Resolved to
            contacts at sweep time, so a contact added to the list later is
            picked up without editing the signal. Authors only; at least one of
            contacts_list_ids or author_profile_urls is required in that
            subject.
          items:
            type: string
          maxItems: 20
          type: array
        detects_event_attendance:
          description: >-
            Find the people who said they will be at an event, instead of
            scoring posts against your own use-cases. A post is relevant when
            its own author says they will be at a specific, named event that has
            not happened yet; a recap, an announcement of someone else's
            attendance, or a bare hashtag is not. Each relevant post reports the
            event's name, start date, location and the author's role (attending,
            speaking, hosting, exhibiting, sponsoring). Costs one post credit
            per post judged, like the AI judge, and use_cases become optional.
            Cannot be combined with accept_all_posts or post_filter, and not
            available on the authors subject.
          type: boolean
        is_enabled:
          description: Defaults to true.
          type: boolean
        keyword_queries:
          description: >-
            One to 10 short LinkedIn content queries, each run as its own search
            and passed through as written: "lean manufacturing", "visual
            management", "kaizen OR gemba". Quote a phrase with the straight
            quote only: a typographic one (“ ” « ») is straightened for you,
            because LinkedIn reads no other kind. Keep each one short (1 to 4
            words, one quoted phrase, or a small OR group): LinkedIn's content
            search returns almost nothing for a long query with several ANDs and
            many quoted phrases. Test candidates with the query tester in the
            app. At least one of keyword_queries, company_linkedin_ids or
            author_profile_urls is required.
          items:
            type: string
          maxItems: 10
          type:
            - array
            - 'null'
        max_contacts_per_sweep:
          description: >-
            Authors cost dial: how many contacts have their posts fetched per
            sweep, least-recently-checked first, so a large list drains over
            several sweeps. One LinkedinContentSignalAuthor credit each.
            Defaults to 50.
          format: int32
          maximum: 500
          minimum: 1
          type: integer
        max_engagers_per_post:
          description: >-
            How many likers and how many commenters are read per relevant post.
            Defaults to 25.
          format: int32
          maximum: 500
          minimum: 1
          type: integer
        max_posts_per_contact:
          description: >-
            Authors cost dial: how many of each watched contact's recent posts
            are fetched and judged. Defaults to 10.
          format: int32
          maximum: 50
          minimum: 1
          type: integer
        max_posts_per_sweep:
          description: >-
            How many new posts one pass of a sweep reads and, at most, judges (a
            sweep runs up to 10 passes until it has collected about 50 people or
            finds nothing new). Defaults to 10.
          format: int32
          maximum: 1000
          minimum: 1
          type: integer
        mentioned_company_linkedin_ids:
          description: >-
            Engagers only: numeric LinkedIn company IDs the posts must mention
            (tag), whoever wrote them, e.g. posts tagging a competitor. Several
            IDs match a post mentioning any of them. Combined with
            keyword_queries and the authors into the same searches, so keywords
            plus a mention finds posts that say the words AND tag the company.
            Counts as a search on its own.
          items:
            type: string
          type:
            - array
            - 'null'
        mentioned_profile_urls:
          description: >-
            Engagers only: LinkedIn profile URLs
            (https://www.linkedin.com/in/<name>) of people the posts must
            mention (tag), whoever wrote them. Several people match a post
            mentioning any of them. The encoded member ID is resolved at sweep
            time; when none of the mentioned people can be resolved and no
            mentioned company is set, the sweep fails with their names rather
            than searching without the mention. Counts as a search on its own.
            For posts mentioning the people of an authors signal, use
            post_sources instead.
          items:
            type: string
          type:
            - array
            - 'null'
        min_engagements:
          description: >-
            Only consider posts with reactions + comments >= this. Defaults to
            0.
          format: int32
          minimum: 0
          type: integer
        name:
          description: Your label for this signal. Unique per account.
          minLength: 1
          type: string
        post_filter:
          description: >-
            Decide relevance with your own keyword rule instead of the AI judge:
            a boolean expression over the post's text, e.g. "lean manufacturing"
            OR kaizen NOT hiring. Words, quoted phrases, AND, OR, NOT and
            parentheses; two words side by side are an AND; matching is
            case-insensitive and word-bounded. Every post the search returns is
            then judged by the rule alone, at no post credit, and use_cases
            become optional. Cannot be combined with accept_all_posts.
          maxLength: 500
          type: string
        post_sources:
          description: >-
            Authors only: which of a watched person's posts count. authored (the
            default) is what they wrote themselves; mentioned is posts by anyone
            that tag them, answering "is anyone talking about this person?".
            Both together reads both corpora. mentioned costs more than authored
            -- one search per contact per sweep, plus a one-off profile lookup
            for each contact whose LinkedIn member ID is not already known --
            and it can answer nothing for a contact with no LinkedIn profile,
            which the per-contact counters report separately. Billed as
            LinkedinContentSignalMention, one per contact searched.
          items:
            enum:
              - authored
              - mentioned
            type: string
          maxItems: 2
          type: array
        search_sort:
          description: >-
            Engagers only: the order the searches ask LinkedIn for. date_posted
            (the default, LinkedIn's Latest) reads the newest posts of the
            window first; relevance (Top match) reads the posts LinkedIn finds
            most relevant to the query first, for a broad query where the newest
            posts are mostly noise. The sweep's date window applies to both.
            Rejected for the authors subject unless date_posted.
          enum:
            - date_posted
            - relevance
          type: string
        search_window:
          description: >-
            Engagers only: how far back the searches look, and so the oldest a
            post may be to count. Omit to follow sweep_frequency: daily reads
            the past week, weekly and once the past month. Rejected when shorter
            than the time between two sweeps (past_24h on a weekly signal), and
            for the authors subject.
          enum:
            - past_24h
            - past_week
            - past_month
          type: string
        subject:
          description: >-
            What the signal watches. engagers (default): search LinkedIn for
            posts and collect the people who liked or commented on the relevant
            ones. authors: take people you already know -- the contacts lists
            below -- and judge their own posts, answering "has this person
            posted about this?" per contact. The use-cases mean the same thing
            in both.
          enum:
            - engagers
            - authors
          type: string
        use_cases:
          description: >-
            One to 10 named use-cases, each with its own AI prompt: what a post
            must be about to fall into it. A post is relevant when it falls into
            at least one; ambiguous posts match nothing. The names are stamped
            on the engagers. Optional when accept_all_posts is true, required
            otherwise.
          items:
            $ref: '#/components/schemas/LinkedinContentSignalUseCaseDto'
          maxItems: 10
          type:
            - array
            - 'null'
      required:
        - name
        - use_cases
      type: object
    LinkedinContentSignalDto:
      additionalProperties: false
      properties:
        accept_all_posts:
          description: >-
            When true, every post the search returns is taken as relevant
            without the AI judge (no LinkedinPostAnalyzed credit); the people
            who engaged are still filtered on their headline and billed.
            Use-cases are optional in that mode.
          type: boolean
        author_profile_urls:
          description: >-
            LinkedIn profile URLs of people whose posts are searched, normalised
            to https://www.linkedin.com/in/<name>. Authors (companies and
            people) are a union, combined with keywords into one search.
          items:
            type: string
          type:
            - array
            - 'null'
        collection:
          description: >-
            Engagers only: which person a relevant post yields. engagers (the
            default): the people who liked or commented on it. post_authors: the
            person who wrote it -- the one shopping in public when the post
            itself is the buying signal. Posts written by a company page have no
            person and are skipped. Each collected author is one event with
            interaction_type Author, filtered and billed like an engager.
          enum:
            - engagers
            - post_authors
          type: string
        company_linkedin_ids:
          description: >-
            Numeric LinkedIn company IDs whose posts are searched. Combined with
            each keyword query into one search.
          items:
            type: string
          type:
            - array
            - 'null'
        contacts_list_ids:
          description: >-
            Contacts lists whose members an authors signal watches. Resolved to
            contacts at sweep time, so a contact added to the list later is
            picked up without editing the signal. Authors only; at least one of
            contacts_list_ids or author_profile_urls is required in that
            subject.
          items:
            type: string
          type:
            - array
            - 'null'
        created_at:
          format: date-time
          type: string
        detects_event_attendance:
          description: >-
            Whether the built-in event rule is this signal's relevance rule: a
            post is relevant when its author said they will be at a named,
            upcoming event. The event found is reported on the post.
          type: boolean
        id:
          type: string
        is_enabled:
          description: >-
            A disabled signal is not swept and costs nothing, but keeps its
            history.
          type: boolean
        keyword_queries:
          description: >-
            The short LinkedIn content queries, exactly as you wrote them. Each
            one runs as its own search. Empty for a search that only follows
            companies or people.
          items:
            type: string
          type:
            - array
            - 'null'
        last_sweep_engagers_collected:
          description: >-
            How many people the last run collected from relevant posts. Each one
            cost one LinkedinContentSignalEngager credit.
          format: int32
          type: integer
        last_sweep_outcome:
          description: >-
            What the last run did. One of:


            - completed: it ran; last_sweep_posts_analyzed and
            last_sweep_engagers_collected say what it did. Zero is a real
            answer.

            - out_of_credits: skipped before spending, because the account could
            not pay for a single post analysis or a single engager. **This is
            the one to check when a feed goes quiet** — topping up resumes it on
            the next sweep.

            - failed: it ran and something went wrong, usually the provider.
            Self-correcting, since the next sweep re-reads an overlapping
            window.
          type: string
        last_sweep_posts_analyzed:
          description: >-
            How many posts the last run had the AI judge. Each one cost one
            LinkedinPostAnalyzed credit; cached re-finds are not counted.
          format: int32
          type: integer
        last_swept_at:
          description: When this signal last ran. Absent until its first sweep.
          format: date-time
          type: string
        max_contacts_per_sweep:
          description: >-
            Authors cost dial: how many contacts have their posts fetched per
            sweep, least-recently-checked first, so a large list drains over
            several sweeps. One LinkedinContentSignalAuthor credit each.
            Defaults to 50.
          format: int32
          type: integer
        max_engagers_per_post:
          description: >-
            Cost dial: how many likers and how many commenters are read per
            relevant post.
          format: int32
          type: integer
        max_posts_per_contact:
          description: >-
            Authors cost dial: how many of each watched contact's recent posts
            are fetched and judged. Defaults to 10.
          format: int32
          type: integer
        max_posts_per_sweep:
          description: >-
            Cost dial: how many new posts one pass of a sweep reads and, at
            most, judges. A sweep runs up to 10 passes, each reading past the
            posts it already knows, and stops once it has collected about 50
            people or finds nothing new. Re-found posts keep their cached
            verdict and cost nothing.
          format: int32
          type: integer
        mentioned_company_linkedin_ids:
          description: >-
            Numeric LinkedIn company IDs the posts must mention (tag), whoever
            wrote them. Combined with the keyword queries and authors into the
            same searches.
          items:
            type: string
          type:
            - array
            - 'null'
        mentioned_profile_urls:
          description: >-
            LinkedIn profile URLs of people the posts must mention (tag),
            whoever wrote them, normalised to
            https://www.linkedin.com/in/<name>.
          items:
            type: string
          type:
            - array
            - 'null'
        min_engagements:
          description: Only posts with reactions + comments >= this are considered.
          format: int32
          type: integer
        name:
          description: Your label for this signal. Unique per account.
          examples:
            - Shop-floor visibility pains
          type: string
        post_filter:
          description: >-
            The seller's own relevance rule, when the AI judge is not used: a
            boolean keyword expression over the post's text (words, quoted
            phrases, AND, OR, NOT, parentheses). Empty means the use-cases and
            the AI judge decide. When set, every post the search returns is
            judged by the rule alone, at no LinkedinPostAnalyzed credit, and
            use-cases are optional.
          type: string
        post_sources:
          description: >-
            Authors only: which of a watched person's posts count. authored (the
            default) is what they wrote themselves; mentioned is posts by anyone
            that tag them, answering "is anyone talking about this person?".
            Both together reads both corpora. mentioned costs more than authored
            -- one search per contact per sweep, plus a one-off profile lookup
            for each contact whose LinkedIn member ID is not already known --
            and it can answer nothing for a contact with no LinkedIn profile,
            which the per-contact counters report separately. Billed as
            LinkedinContentSignalMention, one per contact searched.
          items:
            type: string
          type:
            - array
            - 'null'
        search_sort:
          description: >-
            The order the searches ask LinkedIn for. date_posted (LinkedIn's
            Latest): the newest posts of the window first. relevance (Top
            match): the posts LinkedIn finds most relevant to the query first,
            which suits a broad query. The sweep's date window applies to both.
          enum:
            - date_posted
            - relevance
          type: string
        search_window:
          description: >-
            How far back the searches look, and so the oldest a post may be to
            count: past_24h, past_week or past_month. Empty when the window
            follows sweep_frequency (daily reads the past week, weekly and once
            the past month).
          type: string
        subject:
          description: >-
            What the signal watches. engagers (default): search LinkedIn for
            posts and collect the people who liked or commented on the relevant
            ones. authors: take people you already know -- the contacts lists
            below -- and judge their own posts, answering "has this person
            posted about this?" per contact. The use-cases mean the same thing
            in both.
          enum:
            - engagers
            - authors
          type: string
        updated_at:
          format: date-time
          type: string
        use_cases:
          description: >-
            Ordered list of named use-cases, each with its own AI prompt. A post
            is relevant when it falls into at least one; the names are stamped
            on the engagers it yields.
          items:
            $ref: '#/components/schemas/LinkedinContentSignalUseCaseDto'
          type:
            - array
            - 'null'
      required:
        - id
        - name
        - keyword_queries
        - company_linkedin_ids
        - author_profile_urls
        - mentioned_company_linkedin_ids
        - mentioned_profile_urls
        - min_engagements
        - use_cases
        - max_posts_per_sweep
        - max_engagers_per_post
        - is_enabled
        - search_sort
        - search_window
        - accept_all_posts
        - post_filter
        - detects_event_attendance
        - subject
        - contacts_list_ids
        - max_contacts_per_sweep
        - max_posts_per_contact
        - post_sources
        - collection
        - created_at
        - updated_at
      type: object
    ErrorModel:
      additionalProperties: false
      properties:
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
          examples:
            - Property foo is required but is missing.
          type: string
        errors:
          description: Optional list of individual error details
          items:
            $ref: '#/components/schemas/ErrorDetail'
          type:
            - array
            - 'null'
        instance:
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
          examples:
            - https://example.com/error-log/abc123
          format: uri
          type: string
        status:
          description: HTTP status code
          examples:
            - 400
          format: int64
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This value
            should not change between occurrences of the error.
          examples:
            - Bad Request
          type: string
        type:
          default: about:blank
          description: A URI reference to human-readable documentation for the error.
          examples:
            - https://example.com/errors/example
          format: uri
          type: string
      type: object
    LinkedinContentSignalUseCaseDto:
      additionalProperties: false
      properties:
        name:
          description: >-
            Short label shown as a chip on every engager whose post fell into
            this use-case.
          examples:
            - Lean
          minLength: 1
          type: string
        prompt:
          description: >-
            The AI prompt: what a post must be about to fall into this use-case.
            Judged on its own, independently of the other use-cases.
          examples:
            - >-
              The post mentions lean, kaizen or continuous improvement on the
              shop floor.
          minLength: 1
          type: string
      required:
        - name
        - prompt
      type: object
    ErrorDetail:
      additionalProperties: false
      properties:
        location:
          description: >-
            Where the error occurred, e.g. 'body.items[3].tags' or
            'path.thing-id'
          type: string
        message:
          description: Error message text
          type: string
        value:
          description: The value at the given location
      type: object
  securitySchemes:
    apikeyAuth:
      description: Account API key passed in the Authorization header
      in: header
      name: Authorization
      type: apiKey
    bearerAuth:
      description: Bearer JWT obtained via the OAuth 2.1 authorization flow
      scheme: bearer
      type: http

````