# Market Signals

### Market Signals

Market Signals let you set up automated monitoring subscriptions that continuously scan external data sources and deliver matching signals to your webhook.

**Supported signal types:**

| Type                | What it monitors                                                                                |
| ------------------- | ----------------------------------------------------------------------------------------------- |
| `JOB_POSTS`         | New job postings matching title, skill, company, and location criteria                          |
| `LINKEDIN_POST`     | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |
| `FUND_RAISED`       | Fund closings and fundraising events (web scraping + SEC EDGAR)                                 |
| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR)                   |
| `IPO`               | IPO filings and public listing announcements (web scraping + SEC EDGAR)                         |

**Typical workflow:**

1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL
2. Subscription automatically polls on the configured interval (daily or weekly)
3. New matching signals are delivered to your webhook as batched payloads
4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals
5. Use pause/resume/trigger endpoints to control the subscription lifecycle

**AI-powered filter generation (JOB\_POSTS):**

Instead of manually defining filters, you can provide a natural language `prompt` and the AI will generate complete filter configurations. You can also combine a prompt with partial filters for hybrid mode, where the AI augments your filters with additional criteria inferred from the prompt.

**LinkedIn integration:**

LINKEDIN\_POST subscriptions require a connected LinkedIn Sales Navigator account via the Saber Chrome extension. The subscription uses boolean keyword search combined with AI-based content quality and persona/company filtering to surface high-relevance posts.

## List all market signal subscriptions for your organization

> Retrieve a paginated list of market signal subscriptions. By default, deleted subscriptions\
> are excluded. Set \`includeDeleted=true\` to include them.\
> \
> Results are sorted by creation date (latest first).<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"MarketSignalSubscriptionListResponse":{"type":"object","description":"Paginated list of market signal subscriptions","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MarketSignalSubscriptionResponse"}},"total":{"type":"integer","description":"Total number of subscriptions matching the query"},"limit":{"type":"integer","description":"Maximum subscriptions per page"},"offset":{"type":"integer","description":"Number of subscriptions skipped"}},"required":["items","total","limit","offset"]},"MarketSignalSubscriptionResponse":{"type":"object","description":"A market signal subscription with its current configuration and status","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the subscription"},"organizationId":{"type":"string","description":"Organization that owns this subscription"},"type":{"type":"string","description":"The subscription type (immutable after creation)","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","nullable":true,"description":"Display name for the subscription"},"status":{"type":"string","description":"Current subscription status (derived from timestamps)","enum":["active","paused","deleted"]},"prompt":{"type":"string","nullable":true,"description":"Natural language prompt used for filter generation (if applicable)"},"filters":{"type":"object","description":"The active filter configuration (structure varies by subscription type)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Webhook delivery URL"},"intervalSignalLimit":{"type":"integer","description":"Maximum signals per polling interval"},"interval":{"type":"string","description":"Polling interval","enum":["daily","weekly"]},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription was last updated"}},"required":["id","organizationId","type","status","filters","webhookUrl","intervalSignalLimit","interval","createdAt","updatedAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions":{"get":{"summary":"List all market signal subscriptions for your organization","description":"Retrieve a paginated list of market signal subscriptions. By default, deleted subscriptions\nare excluded. Set `includeDeleted=true` to include them.\n\nResults are sorted by creation date (latest first).\n","operationId":"listMarketSignalSubscriptions","tags":["Market Signals"],"parameters":[{"name":"limit","in":"query","description":"Maximum number of subscriptions to return (1-100, default 20)","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","description":"Number of subscriptions to skip for pagination (default 0)","schema":{"type":"integer","minimum":0,"default":0}},{"name":"includeDeleted","in":"query","description":"Include soft-deleted subscriptions in the response","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Subscriptions retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalSubscriptionListResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Create a market signal subscription to monitor job posts, LinkedIn posts, fundraising, investments, or IPOs

> Create a subscription that continuously monitors external data sources and delivers matching signals\
> to your webhook. Subscriptions run on a configurable polling interval (daily or weekly) and\
> automatically detect and deliver new signals as they appear.\
> \
> \---\
> \
> \## Subscription Types\
> \
> \| Type | Description | Data Source |\
> \|---|---|---|\
> \| \`JOB\_POSTS\` | Monitor new job postings matching your criteria | Job posting aggregators |\
> \| \`LINKEDIN\_POST\` | Monitor LinkedIn posts matching keyword filters | LinkedIn (requires Sales Navigator) |\
> \| \`FUND\_RAISED\` | Monitor fund closings and fundraising events | Web scraping + SEC EDGAR |\
> \| \`RECENT\_INVESTMENT\` | Monitor recent investment and funding rounds | Web scraping + SEC EDGAR |\
> \| \`IPO\` | Monitor IPO and public listing announcements | Web scraping + SEC EDGAR |\
> \
> \---\
> \
> \## Filter Modes\
> \
> Filters can be provided in three ways:\
> \
> 1\. \*\*Prompt only\*\* (JOB\_POSTS): Provide a natural language \`prompt\` and the AI generates complete filters\
> 2\. \*\*Prompt + filters\*\* (JOB\_POSTS): Provide both; the AI augments your filters with prompt intent\
> 3\. \*\*Filters only\*\*: Provide structured filters directly (required for LINKEDIN\_POST)\
> \
> \---\
> \
> \## Webhook Delivery\
> \
> Matched signals are batched and delivered to your \`webhookUrl\` on each polling interval.\
> Each delivery includes an array of signal objects with metadata, payload, and confidence scores.\
> Use \`webhookSecret\` to verify webhook signatures via HMAC-SHA256.\
> \
> \---\
> \
> \## LinkedIn Post Requirements\
> \
> LINKEDIN\_POST subscriptions require a connected LinkedIn Sales Navigator account.\
> If no connector is found, the request returns an error with setup instructions.<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"CreateMarketSignalSubscriptionRequest":{"type":"object","required":["type","webhookUrl"],"properties":{"type":{"type":"string","description":"The type of market signal to monitor. Determines which data sources are polled\nand which filter schema is accepted.\n","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","description":"Optional display name for the subscription","maxLength":200},"prompt":{"type":"string","description":"Natural language prompt for AI-based filter generation (JOB_POSTS only).\nWhen provided without filters, the AI generates complete filters from the prompt.\nWhen provided with filters, the AI augments the filters with prompt intent.\nNot yet supported for LINKEDIN_POST.\n"},"filters":{"type":"object","description":"Subscription filters. The schema depends on the `type` field:\n\n**JOB_POSTS filters:**\n- `titleKeywords` (string[]): Natural language title matching\n- `excludeTitleKeywords` (string[]): Title exclusions\n- `titlePatterns` (string[]): Regex patterns for job titles\n- `excludeTitlePatterns` (string[]): Regex exclusion patterns for titles\n- `descriptionKeywords` (string[]): Description keyword matching\n- `excludeDescriptionKeywords` (string[]): Description exclusions\n- `descriptionPatterns` (string[]): Regex patterns for descriptions\n- `excludeDescriptionPatterns` (string[]): Regex exclusion patterns for descriptions\n- `countries` (string[]): ISO country codes for job location\n- `seniority` (string[]): Seniority levels (c_level, staff, senior, mid_level, junior)\n- `technologySlugs` (string[]): Required technologies\n- `minSalaryUsd` (number): Minimum annual salary in USD\n- `maxSalaryUsd` (number): Maximum annual salary in USD\n- `remote` (boolean): Filter for remote jobs only\n- `companyDomains` (string[]): Specific company domains to monitor\n- `excludeCompanyDomains` (string[]): Company domains to exclude\n- `companyNames` (string[]): Partial match company names\n- `excludeCompanyNames` (string[]): Company names to exclude\n- `minEmployees` (number): Minimum company size\n- `maxEmployees` (number): Maximum company size\n- `companyCountries` (string[]): Company HQ country codes\n- `companyTechnologySlugs` (string[]): Company tech stack filter\n- `excludeRecruitingAgencies` (boolean): Filter out staffing agencies\n- `fundingStages` (string[]): Funding stages (seed, series_a, series_b, etc.)\n- `industryIds` (string[]): LinkedIn industry IDs to include\n- `excludeIndustryIds` (string[]): LinkedIn industry IDs to exclude\n- `promptFilter` (string): AI-based relevance scoring prompt\n- `maxLookbackDays` (number): How far back to look in days\n\n**LINKEDIN_POST filters:**\n- `keywordsAll` (string[]): Boolean AND keywords\n- `keywordsAny` (string[]): Boolean OR keywords\n- `keywordsNone` (string[]): Boolean NOT keywords\n- `promptFilter` (string): AI-based content + persona filtering prompt\n- `maxLookbackDays` (number): Lookback period in days\n\n**FUND_RAISED / RECENT_INVESTMENT / IPO filters (shared):**\n- `searchQueries` (string[]): Custom search queries\n- `keywords` (string[]): Keywords appended to default queries\n- `excludeKeywords` (string[]): Excluded keywords\n- `countries` (string[]): Geographic filtering (reserved)\n- `minAmountUsd` (number): Minimum deal size (reserved)\n- `maxLookbackDays` (number): Lookback period in days\n- `promptFilter` (string): AI-based relevance scoring prompt (reserved)\n\nRequired for LINKEDIN_POST. Optional for JOB_POSTS when `prompt` is provided.\n","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"URL to receive webhook notifications when new signals are matched","maxLength":2048},"webhookSecret":{"type":"string","description":"Optional secret for HMAC-SHA256 webhook signature verification"},"intervalSignalLimit":{"type":"integer","description":"Maximum number of signals to deliver per polling interval (1-10000, default 500)","minimum":1,"maximum":10000,"default":500},"interval":{"type":"string","description":"Polling interval for checking new signals","enum":["daily","weekly"],"default":"daily"}},"additionalProperties":false},"MarketSignalSubscriptionResponse":{"type":"object","description":"A market signal subscription with its current configuration and status","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the subscription"},"organizationId":{"type":"string","description":"Organization that owns this subscription"},"type":{"type":"string","description":"The subscription type (immutable after creation)","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","nullable":true,"description":"Display name for the subscription"},"status":{"type":"string","description":"Current subscription status (derived from timestamps)","enum":["active","paused","deleted"]},"prompt":{"type":"string","nullable":true,"description":"Natural language prompt used for filter generation (if applicable)"},"filters":{"type":"object","description":"The active filter configuration (structure varies by subscription type)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Webhook delivery URL"},"intervalSignalLimit":{"type":"integer","description":"Maximum signals per polling interval"},"interval":{"type":"string","description":"Polling interval","enum":["daily","weekly"]},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription was last updated"}},"required":["id","organizationId","type","status","filters","webhookUrl","intervalSignalLimit","interval","createdAt","updatedAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions":{"post":{"summary":"Create a market signal subscription to monitor job posts, LinkedIn posts, fundraising, investments, or IPOs","description":"Create a subscription that continuously monitors external data sources and delivers matching signals\nto your webhook. Subscriptions run on a configurable polling interval (daily or weekly) and\nautomatically detect and deliver new signals as they appear.\n\n---\n\n## Subscription Types\n\n| Type | Description | Data Source |\n|---|---|---|\n| `JOB_POSTS` | Monitor new job postings matching your criteria | Job posting aggregators |\n| `LINKEDIN_POST` | Monitor LinkedIn posts matching keyword filters | LinkedIn (requires Sales Navigator) |\n| `FUND_RAISED` | Monitor fund closings and fundraising events | Web scraping + SEC EDGAR |\n| `RECENT_INVESTMENT` | Monitor recent investment and funding rounds | Web scraping + SEC EDGAR |\n| `IPO` | Monitor IPO and public listing announcements | Web scraping + SEC EDGAR |\n\n---\n\n## Filter Modes\n\nFilters can be provided in three ways:\n\n1. **Prompt only** (JOB_POSTS): Provide a natural language `prompt` and the AI generates complete filters\n2. **Prompt + filters** (JOB_POSTS): Provide both; the AI augments your filters with prompt intent\n3. **Filters only**: Provide structured filters directly (required for LINKEDIN_POST)\n\n---\n\n## Webhook Delivery\n\nMatched signals are batched and delivered to your `webhookUrl` on each polling interval.\nEach delivery includes an array of signal objects with metadata, payload, and confidence scores.\nUse `webhookSecret` to verify webhook signatures via HMAC-SHA256.\n\n---\n\n## LinkedIn Post Requirements\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account.\nIf no connector is found, the request returns an error with setup instructions.\n","operationId":"createMarketSignalSubscription","tags":["Market Signals"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMarketSignalSubscriptionRequest"}}}},"responses":{"201":{"description":"Subscription created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalSubscriptionResponse"}}}},"400":{"description":"Bad Request - Invalid input or missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity - Validation error (e.g., LinkedIn connector required for LINKEDIN_POST)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Get a market signal subscription by ID

> Retrieve a single market signal subscription including its filter configuration and status.

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"MarketSignalSubscriptionResponse":{"type":"object","description":"A market signal subscription with its current configuration and status","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the subscription"},"organizationId":{"type":"string","description":"Organization that owns this subscription"},"type":{"type":"string","description":"The subscription type (immutable after creation)","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","nullable":true,"description":"Display name for the subscription"},"status":{"type":"string","description":"Current subscription status (derived from timestamps)","enum":["active","paused","deleted"]},"prompt":{"type":"string","nullable":true,"description":"Natural language prompt used for filter generation (if applicable)"},"filters":{"type":"object","description":"The active filter configuration (structure varies by subscription type)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Webhook delivery URL"},"intervalSignalLimit":{"type":"integer","description":"Maximum signals per polling interval"},"interval":{"type":"string","description":"Polling interval","enum":["daily","weekly"]},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription was last updated"}},"required":["id","organizationId","type","status","filters","webhookUrl","intervalSignalLimit","interval","createdAt","updatedAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions/{subscriptionId}":{"get":{"summary":"Get a market signal subscription by ID","description":"Retrieve a single market signal subscription including its filter configuration and status.","operationId":"getMarketSignalSubscription","tags":["Market Signals"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Subscription retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalSubscriptionResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Delete a market signal subscription

> Soft-delete a subscription and stop its polling workflow. The subscription will no longer\
> deliver signals. This operation cannot be undone via the API.<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions/{subscriptionId}":{"delete":{"summary":"Delete a market signal subscription","description":"Soft-delete a subscription and stop its polling workflow. The subscription will no longer\ndeliver signals. This operation cannot be undone via the API.\n","operationId":"deleteMarketSignalSubscription","tags":["Market Signals"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription to delete","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Subscription deleted successfully"},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Update a market signal subscription

> Partially update a subscription's configuration. All fields are optional; only provided\
> fields are updated. The subscription \`type\` is immutable and cannot be changed after creation.\
> \
> When filters or webhook configuration changes, the active polling workflow is\
> automatically refreshed. When the polling interval changes, the workflow is recreated.<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"UpdateMarketSignalSubscriptionRequest":{"type":"object","description":"Partial update for a market signal subscription. All fields are optional; only provided\nfields are updated. The subscription `type` is immutable and cannot be changed.\n","properties":{"name":{"type":"string","description":"Updated display name","maxLength":200},"prompt":{"type":"string","description":"Updated natural language prompt (JOB_POSTS only)"},"filters":{"type":"object","description":"Updated subscription filters (must match the subscription's type schema)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Updated webhook URL","maxLength":2048},"webhookSecret":{"type":"string","description":"Updated webhook secret"},"intervalSignalLimit":{"type":"integer","description":"Updated maximum signals per interval (1-10000)","minimum":1,"maximum":10000},"interval":{"type":"string","description":"Updated polling interval. Changing this recreates the polling workflow.","enum":["daily","weekly"]}},"additionalProperties":false},"MarketSignalSubscriptionResponse":{"type":"object","description":"A market signal subscription with its current configuration and status","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the subscription"},"organizationId":{"type":"string","description":"Organization that owns this subscription"},"type":{"type":"string","description":"The subscription type (immutable after creation)","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","nullable":true,"description":"Display name for the subscription"},"status":{"type":"string","description":"Current subscription status (derived from timestamps)","enum":["active","paused","deleted"]},"prompt":{"type":"string","nullable":true,"description":"Natural language prompt used for filter generation (if applicable)"},"filters":{"type":"object","description":"The active filter configuration (structure varies by subscription type)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Webhook delivery URL"},"intervalSignalLimit":{"type":"integer","description":"Maximum signals per polling interval"},"interval":{"type":"string","description":"Polling interval","enum":["daily","weekly"]},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription was last updated"}},"required":["id","organizationId","type","status","filters","webhookUrl","intervalSignalLimit","interval","createdAt","updatedAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions/{subscriptionId}":{"patch":{"summary":"Update a market signal subscription","description":"Partially update a subscription's configuration. All fields are optional; only provided\nfields are updated. The subscription `type` is immutable and cannot be changed after creation.\n\nWhen filters or webhook configuration changes, the active polling workflow is\nautomatically refreshed. When the polling interval changes, the workflow is recreated.\n","operationId":"updateMarketSignalSubscription","tags":["Market Signals"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription to update","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMarketSignalSubscriptionRequest"}}}},"responses":{"200":{"description":"Subscription updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalSubscriptionResponse"}}}},"400":{"description":"Bad Request - Malformed request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity - Validation error (e.g., invalid webhookUrl or out-of-range intervalSignalLimit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Pause a market signal subscription

> Pause an active subscription. The polling workflow is suspended and no new signals\
> will be delivered until the subscription is resumed. The subscription configuration\
> is preserved.<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"MarketSignalSubscriptionResponse":{"type":"object","description":"A market signal subscription with its current configuration and status","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the subscription"},"organizationId":{"type":"string","description":"Organization that owns this subscription"},"type":{"type":"string","description":"The subscription type (immutable after creation)","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","nullable":true,"description":"Display name for the subscription"},"status":{"type":"string","description":"Current subscription status (derived from timestamps)","enum":["active","paused","deleted"]},"prompt":{"type":"string","nullable":true,"description":"Natural language prompt used for filter generation (if applicable)"},"filters":{"type":"object","description":"The active filter configuration (structure varies by subscription type)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Webhook delivery URL"},"intervalSignalLimit":{"type":"integer","description":"Maximum signals per polling interval"},"interval":{"type":"string","description":"Polling interval","enum":["daily","weekly"]},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription was last updated"}},"required":["id","organizationId","type","status","filters","webhookUrl","intervalSignalLimit","interval","createdAt","updatedAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions/{subscriptionId}/pause":{"post":{"summary":"Pause a market signal subscription","description":"Pause an active subscription. The polling workflow is suspended and no new signals\nwill be delivered until the subscription is resumed. The subscription configuration\nis preserved.\n","operationId":"pauseMarketSignalSubscription","tags":["Market Signals"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription to pause","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Subscription paused successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalSubscriptionResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subscription not found or already paused/deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Resume a paused market signal subscription

> Resume a paused subscription. The polling workflow restarts and signals will\
> be delivered again on the next interval.<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"MarketSignalSubscriptionResponse":{"type":"object","description":"A market signal subscription with its current configuration and status","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the subscription"},"organizationId":{"type":"string","description":"Organization that owns this subscription"},"type":{"type":"string","description":"The subscription type (immutable after creation)","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","nullable":true,"description":"Display name for the subscription"},"status":{"type":"string","description":"Current subscription status (derived from timestamps)","enum":["active","paused","deleted"]},"prompt":{"type":"string","nullable":true,"description":"Natural language prompt used for filter generation (if applicable)"},"filters":{"type":"object","description":"The active filter configuration (structure varies by subscription type)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Webhook delivery URL"},"intervalSignalLimit":{"type":"integer","description":"Maximum signals per polling interval"},"interval":{"type":"string","description":"Polling interval","enum":["daily","weekly"]},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription was last updated"}},"required":["id","organizationId","type","status","filters","webhookUrl","intervalSignalLimit","interval","createdAt","updatedAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions/{subscriptionId}/resume":{"post":{"summary":"Resume a paused market signal subscription","description":"Resume a paused subscription. The polling workflow restarts and signals will\nbe delivered again on the next interval.\n","operationId":"resumeMarketSignalSubscription","tags":["Market Signals"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription to resume","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Subscription resumed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalSubscriptionResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subscription not found or not paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Trigger an immediate run of a market signal subscription

> Trigger an immediate polling run for the subscription, regardless of the normal\
> interval schedule. This is useful for testing a new subscription or forcing a\
> refresh after updating filters.\
> \
> The request succeeds regardless of the subscription's status. However, only\
> subscriptions in \`active\` status will execute the polling workflow and deliver\
> signals. Paused or deleted subscriptions return \`200\` but do not trigger a run.<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"MarketSignalSubscriptionResponse":{"type":"object","description":"A market signal subscription with its current configuration and status","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the subscription"},"organizationId":{"type":"string","description":"Organization that owns this subscription"},"type":{"type":"string","description":"The subscription type (immutable after creation)","enum":["JOB_POSTS","LINKEDIN_POST","FUND_RAISED","RECENT_INVESTMENT","IPO"]},"name":{"type":"string","nullable":true,"description":"Display name for the subscription"},"status":{"type":"string","description":"Current subscription status (derived from timestamps)","enum":["active","paused","deleted"]},"prompt":{"type":"string","nullable":true,"description":"Natural language prompt used for filter generation (if applicable)"},"filters":{"type":"object","description":"The active filter configuration (structure varies by subscription type)","additionalProperties":true},"webhookUrl":{"type":"string","format":"uri","description":"Webhook delivery URL"},"intervalSignalLimit":{"type":"integer","description":"Maximum signals per polling interval"},"interval":{"type":"string","description":"Polling interval","enum":["daily","weekly"]},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription was last updated"}},"required":["id","organizationId","type","status","filters","webhookUrl","intervalSignalLimit","interval","createdAt","updatedAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions/{subscriptionId}/trigger":{"post":{"summary":"Trigger an immediate run of a market signal subscription","description":"Trigger an immediate polling run for the subscription, regardless of the normal\ninterval schedule. This is useful for testing a new subscription or forcing a\nrefresh after updating filters.\n\nThe request succeeds regardless of the subscription's status. However, only\nsubscriptions in `active` status will execute the polling workflow and deliver\nsignals. Paused or deleted subscriptions return `200` but do not trigger a run.\n","operationId":"triggerMarketSignalSubscription","tags":["Market Signals"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription to trigger","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Subscription triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalSubscriptionResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## List signals delivered by a market signal subscription

> Retrieve a paginated list of signals that have been matched and stored by a subscription.\
> Each signal includes the raw payload from the data source (e.g., job posting details,\
> LinkedIn post content, or funding announcement), along with metadata like confidence scores\
> and delivery status.\
> \
> Results are sorted by creation date (latest first).<br>

```json
{"openapi":"3.0.3","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Market Signals","description":"## Market Signals\n\nMarket Signals let you set up automated monitoring subscriptions that continuously scan external data\nsources and deliver matching signals to your webhook.\n\n**Supported signal types:**\n\n| Type | What it monitors |\n|---|---|\n| `JOB_POSTS` | New job postings matching title, skill, company, and location criteria |\n| `LINKEDIN_POST` | LinkedIn posts matching keyword and AI-based persona/content filters (requires Sales Navigator) |\n| `FUND_RAISED` | Fund closings and fundraising events (web scraping + SEC EDGAR) |\n| `RECENT_INVESTMENT` | Recent investment rounds and funding announcements (web scraping + SEC EDGAR) |\n| `IPO` | IPO filings and public listing announcements (web scraping + SEC EDGAR) |\n\n**Typical workflow:**\n\n1. `POST /v1/market-signals/subscriptions` - Create a subscription with type, filters, and webhook URL\n2. Subscription automatically polls on the configured interval (daily or weekly)\n3. New matching signals are delivered to your webhook as batched payloads\n4. `GET /v1/market-signals/subscriptions/{id}/signals` - Browse delivered signals\n5. Use pause/resume/trigger endpoints to control the subscription lifecycle\n\n**AI-powered filter generation (JOB_POSTS):**\n\nInstead of manually defining filters, you can provide a natural language `prompt` and the AI\nwill generate complete filter configurations. You can also combine a prompt with partial filters\nfor hybrid mode, where the AI augments your filters with additional criteria inferred from\nthe prompt.\n\n**LinkedIn integration:**\n\nLINKEDIN_POST subscriptions require a connected LinkedIn Sales Navigator account via the\nSaber Chrome extension. The subscription uses boolean keyword search combined with AI-based\ncontent quality and persona/company filtering to surface high-relevance posts.\n"}],"servers":[{"url":"https://api.saber.app","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key authentication using Bearer token. Format: sk_live_ followed by a secure random string."}},"schemas":{"MarketSignalListResponse":{"type":"object","description":"Paginated list of market signals for a subscription","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MarketSignalResponse"}},"total":{"type":"integer","description":"Total number of signals for the subscription"},"limit":{"type":"integer","description":"Maximum signals per page"},"offset":{"type":"integer","description":"Number of signals skipped"}},"required":["items","total","limit","offset"]},"MarketSignalResponse":{"type":"object","description":"A single market signal matched by a subscription","properties":{"id":{"type":"string","description":"Unique identifier for the signal"},"subscriptionId":{"type":"string","format":"uuid","description":"The subscription that matched this signal"},"jobPostingId":{"type":"string","nullable":true,"description":"Internal job posting ID (for JOB_POSTS signals)"},"externalSignalId":{"type":"string","nullable":true,"description":"External identifier from the data source (e.g., LinkedIn post URN, EDGAR filing ID)"},"payload":{"type":"object","nullable":true,"description":"Raw payload from the data source. Structure varies by subscription type:\n\n**JOB_POSTS**: Job posting details (title, company, location, description, URL, etc.)\n**LINKEDIN_POST**: Post content, author info, engagement metrics, company data\n**FUND_RAISED / RECENT_INVESTMENT / IPO**: Announcement details, amounts, companies involved\n","additionalProperties":true},"confidenceScore":{"type":"number","nullable":true,"format":"float","minimum":0,"maximum":1,"description":"AI confidence score for the signal's relevance (0-1)"},"status":{"type":"string","description":"Delivery status of the signal","enum":["pending","delivered","skipped"]},"publishedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the original content was published at the source"},"createdAt":{"type":"string","format":"date-time","description":"When the signal was matched and stored"},"deliveredAt":{"type":"string","format":"date-time","nullable":true,"description":"When the signal was delivered via webhook (null if not yet delivered)"}},"required":["id","subscriptionId","status","createdAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Additional error details (optional)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["error","message"]}}},"paths":{"/v1/market-signals/subscriptions/{subscriptionId}/signals":{"get":{"summary":"List signals delivered by a market signal subscription","description":"Retrieve a paginated list of signals that have been matched and stored by a subscription.\nEach signal includes the raw payload from the data source (e.g., job posting details,\nLinkedIn post content, or funding announcement), along with metadata like confidence scores\nand delivery status.\n\nResults are sorted by creation date (latest first).\n","operationId":"listMarketSignalSubscriptionSignals","tags":["Market Signals"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","description":"Maximum number of signals to return (1-100, default 20)","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","description":"Number of signals to skip for pagination (default 0)","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Signals retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSignalListResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```
