Skip to main content
POST
Create a post engagement monitor
Post engagement monitoring requires a V2 workspace API key. Legacy V1 API keys are not supported by these endpoints. Monitors and their credits belong to the V2 workspace associated with the key.
Create an active monitor with Bearer authentication. A post engagement monitor follows LinkedIn company pages and personal profiles. On every check it reads the recent posts of each source and finds the people who reacted to or commented on them. Each newly detected engager is added as a row to the monitor’s results table and, when configured, pushed to your webhook. Each successful request creates a new monitor, and creation has no idempotency key. If a network failure leaves the result unknown, list your monitors before retrying; otherwise you may create a second monitor that charges the same people again.
Sources are company pages and profiles only. sources takes 1 to 100 LinkedIn company (/company/...) or profile (/in/...) URLs; they are canonicalized and de-duplicated. Single post URLs are rejected with 422 invalid_monitor; use Post likers or Post commenters for one post.

Settings

  • frequency: daily (default) or weekly.
  • engagement_types: any of reactions and comments; default both.
  • include_existing_engagers: default false, so the first check only records a baseline. true also delivers and charges people who engaged before the monitor existed.
  • filters: titles and locations (case-insensitive contains matches, up to 50 each) and excluded_company_urls (LinkedIn company URLs, up to 100). Engagers that do not match are not delivered or charged.
  • webhook_url: a public HTTPS URL without embedded credentials. Private, loopback, and internal hosts are rejected with 422 before creation and checked again at every send.
Unknown fields are rejected with 422 invalid_monitor. The JSON request body must be at most 256 KiB (262,144 bytes); a larger body returns 413.

Limits and admission

A workspace can hold at most 25 monitors (422 monitor_limit_reached), counting monitors created in the Airscale app. Creation requires at least 0.2 credits (402 insufficient_credits). While post engagement monitoring is closed, creation returns 503 monitoring_not_enabled. The 202 Accepted response contains monitor, sources, signing_secret, and signing_secret_warning. Store signing_secret immediately; it is encrypted at rest and never returned again. Checks run asynchronously: the first check is due immediately and runs within a few minutes. Monitors share a check queue, so under load next_check_at can slip, but nothing is lost.

Credits

Each engager delivered to the results table costs 0.2 credits, charged once per person per monitor however many posts they engage with later. Reading posts and engagement pages is free, and reads, webhook deliveries, redeliveries, mark-read, and configuration changes never spend credits. When credits run out, checks keep running but new engagers wait unpaid: the monitor shows results_status: "blocked" and results_error: "insufficient_credits", and they are charged and delivered within a few minutes of a top-up. Monitors are independent: the same person engaging with sources of two monitors is delivered and charged by each.

Results table

Each monitor owns a regular Airscale results table named <name> — Post engagement. If the table is deleted or full in the app, delivery stops without charging and the monitor reports results_status: "blocked" with the reason. Deleting the monitor keeps its results table.

Verify webhook signatures

One webhook is sent per delivered engager, including existing engagers imported on request. The JSON body has "type": "post_engagement.engager_detected", id (the engager ID), monitor_id, detected_at (the delivery time), engager (the engager object from List engagers without read_at and webhook), and engagements (up to the 25 most recent engagement objects from List engagements). The request includes X-Airscale-Event: post_engagement.engager_detected, X-Airscale-Event-Id: <engager_id>, X-Airscale-Timestamp, X-Airscale-Signature: sha256=<hex>, and Idempotency-Key: post-engagement-engager:<engager_id>. Compute HMAC-SHA256 with the signing_secret over <timestamp>.<raw request body>, compare it in constant time, and reject timestamps more than five minutes from the current time. This is the same scheme as job-change monitor webhooks. Deduplicate on the event ID and return a 2xx response only after durable handling. Deliveries are dispatched every couple of minutes with a 15-second timeout. Airscale makes up to five attempts with exponential backoff: 408, 425, 429, and 5xx responses are retried; other responses fail permanently (webhook_http_<status>); a blocked destination fails with webhook_url_rejected; timeouts and dropped connections become uncertain and are never resent automatically. Use Redeliver a webhook to send an engager again.

Next step

Use Get a post engagement monitor to follow the first check of each source.

Authorizations

Authorization
string
header
required

Use an Airscale workspace API key. Never expose the key in client-side code.

Body

application/json

Provide a name and 1–100 LinkedIn company or profile URLs in a JSON body of at most 256 KiB (262,144 bytes). Unknown fields are rejected.

name
string
required

Also names the results table: <name> — Post engagement.

Required string length: 1 - 120
sources
string[]
required

1–100 LinkedIn company (/company/...) or personal profile (/in/...) URLs. URLs are canonicalized and de-duplicated. Single post URLs are rejected.

Required array length: 1 - 100 elements
Required string length: 1 - 1000
frequency
enum<string>
default:daily
Available options:
daily,
weekly
engagement_types
enum<string>[]
Required array length: 1 - 2 elements
Available options:
reactions,
comments
include_existing_engagers
boolean
default:false

false: the first check only records a baseline. true: people who engaged before the monitor existed are also delivered and charged.

filters
object

Engagers that do not match are not delivered or charged. Titles and locations are case-insensitive contains matches.

webhook_url
string<uri> | null

A public HTTPS URL without embedded credentials. Internal hostnames and private or reserved addresses are rejected, and destinations are checked again at every send.

Maximum string length: 2048

Response

The monitor was accepted and its first check scheduled. Checks run asynchronously; acceptance does not mean a check has completed.

monitor
object
required
sources
object[]
required

The monitor's active sources, sorted by URL.

signing_secret
string | null
required

Returned once when a webhook is configured; null otherwise.

signing_secret_warning
string | null
required