Skip to content

API Reference

Endpoints

POST /apify/linkedin/interactions

Trigger LinkedIn interactions scraping for one or more LinkedIn profiles/companies.

Endpoint: POST /apify/linkedin/interactions

Request Body

Field Type Required Default Description
user_company_id string Yes - User company ID to associate with this scraping job
trigger_user_id string No null Optional trigger user ID to associate with this scraping job
targets List[object] Yes - List of LinkedIn targets to scrape (min 1)
targets[].linkedin_handle string Yes - LinkedIn handle/username (e.g., 'microsoft' or 'john-doe')
targets[].entity string Yes - Entity type: 'PERSON' or 'COMPANY'
posted_limit string No "any" Filter posts by age: "any", "24h", "week", "month", "3months", "6months"
max_posts integer No 10 Maximum posts to scrape per profile (0 = unlimited)
scrape_reactions boolean No true Whether to scrape post reactions
max_reactions integer No 5 Maximum reactions per post (min 1)
scrape_comments boolean No true Whether to scrape post comments
max_comments integer No 5 Maximum comments per post (min 1)
comments_posted_limit string No "any" Filter comments by age: "any", "24h", "week", "month"

Example Request

{
  "user_company_id": "12345678",
  "trigger_user_id": "12345678",
  "targets": [
    {
      "linkedin_handle": "arsenal-f-c",
      "entity": "COMPANY"
    },
    {
      "linkedin_handle": "realmadrid",
      "entity": "COMPANY"
    },
    {
      "linkedin_handle": "john-doe",
      "entity": "PERSON"
    }
  ],
  "posted_limit": "any",
  "max_posts": 10,
  "scrape_reactions": true,
  "max_reactions": 10,
  "scrape_comments": true,
  "max_comments": 5,
  "comments_posted_limit": "any"
}

Example Response

{
  "success": true,
  "message": "Triggered 3/3 jobs successfully.",
  "user_company_id": "12345678",
  "trigger_user_id": "12345678",
  "total_targets": 3,
  "successful_count": 3,
  "failed_count": 0,
  "results": [
    {
      "linkedin_handle": "arsenal-f-c",
      "entity": "COMPANY",
      "run_id": "abc123xyz",
      "success": true,
      "error": null
    },
    {
      "linkedin_handle": "realmadrid",
      "entity": "COMPANY",
      "run_id": "def456uvw",
      "success": true,
      "error": null
    },
    {
      "linkedin_handle": "john-doe",
      "entity": "PERSON",
      "run_id": "ghi789rst",
      "success": true,
      "error": null
    }
  ]
}

What Happens Next

  1. Each target gets a separate Apify scraping job
  2. Jobs are tracked in the environment-specific tracker table with status PENDING
  3. When Apify completes scraping (typically 5-20 minutes), it sends a webhook event
  4. Webhook handler processes the data and saves to BigQuery tables
  5. Tracker table status is updated to COMPLETED with data counts

Checking Status

Query the tracker table to check job status (use the table matching your environment):

-- Production: linkedin.ApifyInteractionsTrackerTable
-- Staging: linkedin.ApifyInteractionsTrackerTableStaging
-- Dev: linkedin.ApifyInteractionsTrackerTableDev

SELECT
  linkedinUsername,
  entityType,
  status,
  posts_count,
  reactions_count,
  comments_count,
  created_at,
  completed_date
FROM `linkedin.ApifyInteractionsTrackerTable`
WHERE user_company_id = '12345678'
ORDER BY created_at DESC;


POST /apify/linkedin/abort-run

Abort pending or running Apify runs for specified LinkedIn targets.

Endpoint: POST /apify/linkedin/abort-run

Request Body

Field Type Required Default Description
user_company_id string Yes - User company ID to find and abort runs for
targets List[object] Yes - List of LinkedIn targets to abort (min 1)
targets[].linkedin_handle string Yes - LinkedIn handle/username
targets[].entity string Yes - Entity type: 'PERSON' or 'COMPANY'

Example Request

{
  "user_company_id": "12345678",
  "targets": [
    {
      "linkedin_handle": "arsenal-f-c",
      "entity": "COMPANY"
    },
    {
      "linkedin_handle": "realmadrid",
      "entity": "COMPANY"
    }
  ]
}

Example Response

{
  "success": true,
  "message": "Aborted 2/2 runs successfully.",
  "user_company_id": "12345678",
  "total_targets": 2,
  "successful_count": 2,
  "failed_count": 0,
  "results": [
    {
      "linkedin_handle": "arsenal-f-c",
      "entity": "COMPANY",
      "run_id": "abc123xyz",
      "success": true,
      "error": null,
      "status": "ABORTED"
    },
    {
      "linkedin_handle": "realmadrid",
      "entity": "COMPANY",
      "run_id": "def456uvw",
      "success": true,
      "error": null,
      "status": "ABORTED"
    }
  ]
}

Common Error Messages

  • "No pending or running run found" - No active run exists for this target
  • "Run already completed with status {status}" - Run has already finished (SUCCEEDED/FAILED)

GET /health

Health check endpoint for monitoring.

Endpoint: GET /health

Response

{
  "status": "healthy",
  "service": "brand-interactions-pipeline",
  "environment": "staging"
}

Request Validation

  1. targets array: Must contain at least 1 target
  2. linkedin_handle: Cannot be empty (whitespace is trimmed)
  3. entity: Must be exactly "PERSON" or "COMPANY" (case-sensitive)
  4. posted_limit: Must match pattern: ^(any|24h|week|month|3months|6months)$
  5. comments_posted_limit: Must match pattern: ^(any|24h|week|month)$
  6. max_posts: Must be >= 0
  7. max_reactions: Must be >= 1
  8. max_comments: Must be >= 1
  9. posted_limit + max_posts: Cannot combine posted_limit="any" with max_posts=0 (would scrape all posts since profile inception)

Response Behavior

  • Partial Success: If some targets succeed and others fail, success will be true if at least one target succeeded
  • Error Handling: Each target result includes its own success and error fields
  • Run IDs: Only successful targets will have a run_id in the response

BigQuery Tables

Tracker Tables (Environment-Specific)

Tracks the status of each scraping job.

Environment Table
Production linkedin.ApifyInteractionsTrackerTable
Staging linkedin.ApifyInteractionsTrackerTableStaging
Dev linkedin.ApifyInteractionsTrackerTableDev

Key Columns: - linkedinUsername - LinkedIn handle - entityType - "COMPANY" or "PERSON" - status - PENDING, RUNNING, COMPLETED, FAILED, ABORTED - user_company_id - User company ID from request - trigger_user_id - Trigger user ID from request (nullable) - apify_run_id - Apify run ID - posts_count - Number of posts scraped (null until completed) - reactions_count - Number of reactions scraped (null until completed) - comments_count - Number of comments scraped (null until completed) - created_at - When job was triggered - completed_date - When job completed/failed

Data Tables

Scraped data is saved to these tables:

  • linkedin.ApifyLinkedinPost - LinkedIn posts data
  • linkedin.ApifyLinkedinPostComment - Post comments data
  • linkedin.ApifyLinkedinPostReaction - Post reactions data

Data is typically available in BigQuery within 5-20 minutes after triggering, depending on the amount of data to scrape.


Expected Input/Output

Input

  • LinkedIn handles: Use the handle from LinkedIn URLs (e.g., microsoft from linkedin.com/company/microsoft)
  • Entity type: Specify "COMPANY" or "PERSON" based on the profile type
  • Scraping limits: Configure how many posts, reactions, and comments to scrape

Output

  • Immediate: API returns run IDs and success status for each target
  • After completion: Data is available in BigQuery tables (posts, comments, reactions)
  • Status tracking: Check tracker table for job status and data counts