Query Contents

Paginate the content items collected for your workspace.

Content endpoints expose content created or collected for the authenticated workspace.

POST/api/v2/contents/query

Request body

FieldTypeDescription
pageintegerPage number (default 1).
page_sizeintegerNumber of items per page (default 25).
date_fromstringISO 8601 timestamp. Include content created at or after this date.
date_tostringISO 8601 timestamp. Include content created at or before this date.
content_typestring[]Filter by content type. Native JSON array. Valid values: linkedinComment, recentlyPromoted, linkedinPost, linkedinCompanyPost, linkedinJobPosting, webArticle, pressRelease, blogPost.
company_idintegerFilter by company numeric SQL id. Takes priority over all human-identifier fields.
company_domainstring[]Filter by company domain(s). Native JSON array. Maximum 100 values. Resolved to company IDs via a single-winning-tier waterfall: company_id > company_linkedin_handle > company_linkedin_url > company_domain. Only the highest-priority supplied tier is used.
company_linkedin_handlestring[]Filter by company LinkedIn handle(s) (slug, e.g. acme-corp). Native JSON array. Maximum 100 values. See company_domain for tier priority.
company_linkedin_urlstring[]Filter by company LinkedIn URL(s) (e.g. https://www.linkedin.com/company/acme-corp). Native JSON array. Maximum 100 values. See company_domain for tier priority.
lead_idintegerFilter for content authored by one lead. Use the lead_id shown on each content item, returned by the signals endpoints, or from the lead lookup endpoint.
response_formatstringControls whether the data field is included and how detailed it is. Valid values: normalized (default), concise, detailed (deprecated alias of normalized). See Response formats.

Response formats

The response_format field controls what each item's data field contains:

  • normalized (default): a clean, type-specific object built from the underlying content. See the shapes below.
  • concise: the data field is omitted entirely. Lowest token footprint, useful when you only need ids, types and timestamps.
  • detailed: deprecated alias of normalized, kept for backward compatibility. Use normalized going forward.

Every field inside data is best-effort: a field the underlying content does not carry (engagement, mentions, images, …) is simply omitted rather than sent as null.

engagement uses the same flat shape for posts and comments: likes, comments (comments on a post, or replies to a comment), shares (posts only), and a per-reaction-type breakdown — praise, empathy, interest, appreciation — whenever the source exposes it.

LinkedIn posts (linkedinPost, linkedinCompanyPost)

{
  "post_id": "7440055204630249472",
  "original_post_id": "7439950617915080704",
  "is_repost": true,
  "link": "https://www.linkedin.com/posts/sillage-signals_last-week-arnaud-weiss-and-arthur-coudouy-activity-7440055204630249472-vKkM",
  "text": "Thank you for featuring us! 🔥",
  "posted_at": "2026-03-18T15:23:10.325Z",
  "engagement": { "likes": 1, "comments": 0, "shares": 0, "praise": 0, "empathy": 0 },
  "author": {
    "type": "company",
    "company_name": "Sillage",
    "linkedin_url": "https://www.linkedin.com/company/sillage-signals/"
  },
  "mentions": {
    "profiles": [
      {
        "name": "Arnaud Weiss",
        "linkedin_url": "https://www.linkedin.com/in/arnaud-weiss-60b6758a"
      }
    ],
    "companies": [
      {
        "name": "Salesforce",
        "linkedin_url": "https://www.linkedin.com/company/salesforce/"
      }
    ]
  },
  "images": [
    "https://media.licdn.com/dms/image/v2/D4E22AQE.../feedshare-shrink_800/0/1710000000000"
  ]
}

images is an array of image URL strings attached to the post, in no particular order.

author.type is profile or company. Profile authors carry full_name, headline (nullable), and linkedin_url; company authors carry company_name and linkedin_url (no headline). A repost keeps this same flat shape: is_repost is true and original_post_id points at the original post, which you can fetch separately if you need its own content.

Each entry in mentions.profiles and mentions.companies is intentionally lightweight — just name and linkedin_url, with no type discriminator — since which array the entry appears in already tells you whether it's a profile or a company.

LinkedIn comments (linkedinComment)

{
  "linkedin_id": "7175492449631371265",
  "text": "Congrats on the launch!",
  "linkedin_url": "https://www.linkedin.com/feed/update/urn:li:activity:123?commentUrn=456",
  "posted_at": "2026-03-18T15:05:14.196Z",
  "engagement": {
    "comments": 0,
    "likes": 1,
    "praise": 0,
    "empathy": 0,
    "interest": 0,
    "appreciation": 0
  },
  "author": {
    "type": "profile",
    "full_name": "Jean Dupont",
    "headline": "VP Sales @ Acme",
    "linkedin_url": "https://www.linkedin.com/in/jeandupont"
  },
  "post_content_id": 10762
}

linkedin_id is the comment's own LinkedIn id and linkedin_url links to it on LinkedIn. posted_at is when the comment was left. engagement.comments is the number of replies to this comment; engagement.likes and the reaction breakdown work the same way as on posts. author is the person who left the comment. post_content_id is the workspace content ID of the post the comment was left on — pass it to GET /api/v2/contents/{id} to fetch the full post. It is null when that post is not among your workspace's contents.

LinkedIn job postings (linkedinJobPosting)

{
  "linkedin_id": "9988776655",
  "linkedin_url": "https://www.linkedin.com/jobs/view/senior-software-engineer-at-sillage-9988776655",
  "title": "Senior Software Engineer",
  "min_salary": null,
  "max_salary": null,
  "location": "Paris, ÃŽle-de-France, France",
  "posted_at": "2025-11-12T00:00:00.000Z",
  "description": "About Us — Sillage helps go-to-market teams turn public signals into pipeline…"
}

linkedin_id is the job posting's own LinkedIn id. description is the full plain-text job description. min_salary and max_salary are null when LinkedIn does not expose a salary range for the posting. As with the other shapes, any field the underlying content does not carry is omitted rather than sent as null.

LinkedIn reactions (linkedinReaction)

linkedinReaction cannot be requested through content_type on this endpoint, but a reaction can still be returned when you fetch a stored content item directly by id with GET /api/v2/contents/{id}.

{
  "reaction_type": "CELEBRATE",
  "author": {
    "type": "profile",
    "full_name": "Jean Dupont",
    "headline": "VP Sales @ Acme",
    "linkedin_url": "https://www.linkedin.com/in/jeandupont"
  },
  "post": {
    "post_id": "7440055204630249472",
    "link": "https://www.linkedin.com/posts/sillage-signals_activity-7440055204630249472",
    "text": "We just closed our pre-seed…",
    "author": {
      "type": "company",
      "company_name": "Sillage",
      "linkedin_url": "https://www.linkedin.com/company/sillage-signals/"
    }
  }
}

Other content types

For every other content_type, data is { "text": "…" } when text content is available, and omitted entirely otherwise.

Example request

curl -X POST "https://api.getsillage.com/api/v2/contents/query" \
  -H "Authorization: Bearer $SILLAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"page":1,"page_size":10,"company_domain":["acme.com","example.com"]}'
const response = await fetch('https://api.getsillage.com/api/v2/contents/query', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SILLAGE_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    page: 1,
    page_size: 10,
    company_domain: ['acme.com', 'example.com'],
  }),
})

const result = await response.json()
import { request } from 'node:https'

const body = JSON.stringify({
  page: 1,
  page_size: 10,
  company_domain: ['acme.com', 'example.com'],
})

const req = request(
  new URL('https://api.getsillage.com/api/v2/contents/query'),
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.SILLAGE_API_KEY}`,
      'Content-Type': 'application/json',
      'Content-Length': Buffer.byteLength(body),
    },
  },
  (res) => {
    let data = ''
    res.on('data', (chunk) => {
      data += chunk
    })
    res.on('end', () => {
      console.log(JSON.parse(data))
    })
  },
)

req.write(body)
req.end()
import os
import requests

response = requests.post(
    "https://api.getsillage.com/api/v2/contents/query",
    json={
        "page": 1,
        "page_size": 10,
        "company_domain": ["acme.com", "example.com"],
    },
    headers={"Authorization": f"Bearer {os.environ['SILLAGE_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
result = response.json()

Example response

{
  "data": [
    {
      "id": 120384,
      "content_type": "linkedinPost",
      "created_at": "2026-06-12T09:15:00.000Z",
      "data": {
        "post_id": "7440055204630249472",
        "is_repost": false,
        "link": "https://www.linkedin.com/posts/sillage-signals_activity-7440055204630249472-vKkM",
        "text": "Thank you for featuring us! 🔥",
        "posted_at": "2026-06-12T09:00:00.000Z",
        "engagement": { "likes": 12, "comments": 2, "shares": 1 },
        "author": {
          "type": "profile",
          "full_name": "Jean Dupont",
          "headline": "VP Sales @ Acme",
          "linkedin_url": "https://www.linkedin.com/in/jeandupont"
        }
      },
      "lead_id": 3301,
      "company_id": 8421
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "page_size": 10,
      "page_count": 5,
      "total": 47
    },
    "resolved_companies": [
      {
        "company_id": 8421,
        "matched_by": "domain",
        "identifier": "acme.com"
      },
      {
        "company_id": 9103,
        "matched_by": "domain",
        "identifier": "example.com"
      }
    ]
  }
}

meta.resolved_companies

Contains one entry per company matched from a company filter (company_id, company_domain, company_linkedin_handle, or company_linkedin_url).

FieldTypeDescription
company_idintegerNumeric SQL id of the matched company.
matched_bystringWhich identifier tier produced this match. One of: company_id, linkedin_handle, linkedin_url, domain.
identifierstringThe original identifier value supplied by the caller (domain, handle, URL, or numeric id echoed as a string).

All entries share the same matched_by value for a given response — only the single winning tier resolves. When no company filter is supplied, resolved_companies is an empty array.

On this page