# Signal Subscriptions

### Signal Subscriptions

Subscriptions schedule recurring signal executions against a signal template. Each subscription ties a template to a frequency, timezone, and optional targeting (list or domain).

**Lifecycle:**

1. Create a subscription via `POST /v1/companies/signals/subscriptions` (references an existing template or creates one inline)
2. Activate it with `POST /v1/companies/signals/{signalId}/start`
3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`
4. Pause with `POST /v1/companies/signals/{signalId}/stop`

The response merges the template definition with the schedule configuration so you get the full picture in a single object.

## List all signal subscriptions for your organization

> Retrieve a paginated list of signal subscriptions. Each subscription is merged\
> with its signal template data so the response includes the full template definition\
> alongside the schedule configuration.<br>

```json
{"openapi":"3.2.0","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Signal Subscriptions","summary":"Signal Subscriptions","kind":"nav","description":"## Signal Subscriptions\n\nSubscriptions schedule recurring signal executions against a signal template.\nEach subscription ties a template to a frequency, timezone, and optional\ntargeting (list or domain).\n\n**Lifecycle:**\n1. Create a subscription via `POST /v1/companies/signals/subscriptions`\n   (references an existing template or creates one inline)\n2. Activate it with `POST /v1/companies/signals/{signalId}/start`\n3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`\n4. Pause with `POST /v1/companies/signals/{signalId}/stop`\n\nThe response merges the template definition with the schedule configuration\nso you get the full picture in a single object.\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":{"ListSignalSubscriptionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SignalSubscriptionResponse"}},"total":{"type":"integer","description":"Total number of subscriptions matching the query"},"limit":{"type":"integer","description":"Maximum number of subscriptions returned"},"offset":{"type":"integer","description":"Number of subscriptions skipped"},"hasMore":{"type":"boolean","description":"Whether there are more subscriptions available"}},"required":["items","total","limit","offset","hasMore"]},"SignalSubscriptionResponse":{"type":"object","description":"A signal subscription merged with its template definition.","properties":{"id":{"type":"string","format":"uuid","description":"The subscription ID (unique per subscription)."},"signalTemplateId":{"type":"string","format":"uuid","description":"The signal template ID this subscription is based on. Use this to correlate subscriptions that share the same template."},"version":{"type":"integer","description":"Template version number"},"name":{"type":"string","description":"Subscription name if set, otherwise the template name"},"description":{"type":"string"},"question":{"type":"string","description":"The research question"},"answerType":{"type":"string","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"outputSchema":{"type":"object","additionalProperties":true},"weight":{"type":"string","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true},"frequency":{"type":"string","description":"Preset frequency if set","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"The resolved cron expression"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"status":{"type":"string","enum":["active","stopped"]},"listId":{"type":"string","format":"uuid","description":"Contact list ID"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","signalTemplateId","version","name","question","answerType","cronExpression","timezone","status","listId","source","createdAt"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by every endpoint that flows through the global error handler. Note: the global rate-limit middleware (HTTP 429 from per-API-key throttling) returns a different, flat shape — see `RateLimitErrorResponse`.\n","required":["error"],"properties":{"error":{"type":"object","required":["type","code","requestId"],"properties":{"type":{"type":"string","description":"Error category. Maps 1:1 to HTTP status (e.g. VALIDATION → 422, UNAUTHORIZED → 401).","enum":["BAD_REQUEST","VALIDATION","UNPROCESSABLE_ENTITY","NOT_FOUND","CONFLICT","UNAUTHORIZED","FORBIDDEN","PAYMENT_REQUIRED","PAYLOAD_TOO_LARGE","INTERNAL","EXTERNAL","TIMEOUT"]},"code":{"type":"string","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","description":"Human-readable error message. Wording may change; do not match against this string."},"errorCode":{"type":"string","description":"Optional public error code propagated from a downstream service (e.g. NestJS, LinkedIn)."},"errorAction":{"type":"string","description":"Optional user action guidance (e.g. \"reconnect Sales Navigator\")."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured fields forwarded from a downstream service. Shape depends on the source."},"requestId":{"type":"string","format":"uuid","description":"Correlation ID for this request. Include when reporting issues."},"fields":{"type":"array","description":"Per-field validation errors (populated when `type` is `VALIDATION` and the cause is a struct-tag validator).","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"debug":{"type":"object","description":"Debug information. Only present in development environments.","properties":{"cause":{"type":"string"}}}}}}}}},"paths":{"/v1/companies/signals/subscriptions":{"get":{"summary":"List all signal subscriptions for your organization","description":"Retrieve a paginated list of signal subscriptions. Each subscription is merged\nwith its signal template data so the response includes the full template definition\nalongside the schedule configuration.\n","operationId":"listSignalSubscriptions","tags":["Signal Subscriptions"],"parameters":[{"name":"limit","in":"query","description":"Maximum number of subscriptions to return","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","description":"Number of subscriptions to skip for pagination","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Subscriptions retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSignalSubscriptionsResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Create a signal subscription

> Create a subscription that schedules recurring signal executions.\
> \
> You can either reference an existing template via \`signalTemplateId\`, or create a\
> template inline by providing \`name\` and \`question\` (plus optional fields like\
> \`answerType\`, \`description\`, \`weight\`, \`qualificationCriteria\`, \`outputSchema\`).\
> \
> The subscription is created in a stopped state. Use the schedule lifecycle\
> endpoints (\`POST .../start\`) to activate it.<br>

```json
{"openapi":"3.2.0","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Signal Subscriptions","summary":"Signal Subscriptions","kind":"nav","description":"## Signal Subscriptions\n\nSubscriptions schedule recurring signal executions against a signal template.\nEach subscription ties a template to a frequency, timezone, and optional\ntargeting (list or domain).\n\n**Lifecycle:**\n1. Create a subscription via `POST /v1/companies/signals/subscriptions`\n   (references an existing template or creates one inline)\n2. Activate it with `POST /v1/companies/signals/{signalId}/start`\n3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`\n4. Pause with `POST /v1/companies/signals/{signalId}/stop`\n\nThe response merges the template definition with the schedule configuration\nso you get the full picture in a single object.\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":{"CreateSignalSubscriptionRequest":{"type":"object","description":"Exactly one of `frequency` or `cronExpression` must be provided.\nUse `frequency` for preset schedules (daily/weekly/monthly) or\n`cronExpression` for custom cron-based schedules.\n","properties":{"signalTemplateId":{"type":"string","format":"uuid","description":"ID of an existing signal template. If omitted, `name` and `question`\nare required to create a template inline.\n"},"name":{"type":"string","description":"Template name (required when creating inline, ignored when signalTemplateId is provided)","minLength":1,"maxLength":200},"description":{"type":"string","description":"Template description (optional, for inline creation)","maxLength":1000},"question":{"type":"string","description":"Research question (required when creating inline)","minLength":1,"maxLength":500},"answerType":{"type":"string","description":"Expected answer format (for inline creation, defaults to open_text)","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"],"default":"open_text"},"outputSchema":{"type":"object","description":"JSON Schema for custom output (when answerType is json_schema)","additionalProperties":true},"weight":{"type":"string","description":"Importance of the signal (for inline creation)","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","description":"Qualification criteria for scoring answers (for inline creation)","additionalProperties":true},"frequency":{"type":"string","description":"Preset schedule frequency. Mutually exclusive with `cronExpression` —\nexactly one must be provided.\n","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"Custom cron expression (5-field). Mutually exclusive with `frequency` —\nexactly one must be provided.\n"},"timezone":{"type":"string","description":"IANA timezone for scheduling (defaults to UTC)"},"listId":{"type":"string","format":"uuid","description":"Contact list ID to scope signal execution"}},"required":["listId"]},"SignalSubscriptionResponse":{"type":"object","description":"A signal subscription merged with its template definition.","properties":{"id":{"type":"string","format":"uuid","description":"The subscription ID (unique per subscription)."},"signalTemplateId":{"type":"string","format":"uuid","description":"The signal template ID this subscription is based on. Use this to correlate subscriptions that share the same template."},"version":{"type":"integer","description":"Template version number"},"name":{"type":"string","description":"Subscription name if set, otherwise the template name"},"description":{"type":"string"},"question":{"type":"string","description":"The research question"},"answerType":{"type":"string","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"outputSchema":{"type":"object","additionalProperties":true},"weight":{"type":"string","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true},"frequency":{"type":"string","description":"Preset frequency if set","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"The resolved cron expression"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"status":{"type":"string","enum":["active","stopped"]},"listId":{"type":"string","format":"uuid","description":"Contact list ID"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","signalTemplateId","version","name","question","answerType","cronExpression","timezone","status","listId","source","createdAt"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by every endpoint that flows through the global error handler. Note: the global rate-limit middleware (HTTP 429 from per-API-key throttling) returns a different, flat shape — see `RateLimitErrorResponse`.\n","required":["error"],"properties":{"error":{"type":"object","required":["type","code","requestId"],"properties":{"type":{"type":"string","description":"Error category. Maps 1:1 to HTTP status (e.g. VALIDATION → 422, UNAUTHORIZED → 401).","enum":["BAD_REQUEST","VALIDATION","UNPROCESSABLE_ENTITY","NOT_FOUND","CONFLICT","UNAUTHORIZED","FORBIDDEN","PAYMENT_REQUIRED","PAYLOAD_TOO_LARGE","INTERNAL","EXTERNAL","TIMEOUT"]},"code":{"type":"string","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","description":"Human-readable error message. Wording may change; do not match against this string."},"errorCode":{"type":"string","description":"Optional public error code propagated from a downstream service (e.g. NestJS, LinkedIn)."},"errorAction":{"type":"string","description":"Optional user action guidance (e.g. \"reconnect Sales Navigator\")."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured fields forwarded from a downstream service. Shape depends on the source."},"requestId":{"type":"string","format":"uuid","description":"Correlation ID for this request. Include when reporting issues."},"fields":{"type":"array","description":"Per-field validation errors (populated when `type` is `VALIDATION` and the cause is a struct-tag validator).","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"debug":{"type":"object","description":"Debug information. Only present in development environments.","properties":{"cause":{"type":"string"}}}}}}}}},"paths":{"/v1/companies/signals/subscriptions":{"post":{"summary":"Create a signal subscription","description":"Create a subscription that schedules recurring signal executions.\n\nYou can either reference an existing template via `signalTemplateId`, or create a\ntemplate inline by providing `name` and `question` (plus optional fields like\n`answerType`, `description`, `weight`, `qualificationCriteria`, `outputSchema`).\n\nThe subscription is created in a stopped state. Use the schedule lifecycle\nendpoints (`POST .../start`) to activate it.\n","operationId":"createSignalSubscription","tags":["Signal Subscriptions"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSignalSubscriptionRequest"}}}},"responses":{"201":{"description":"Subscription created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalSubscriptionResponse"}}}},"400":{"description":"Bad Request - Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Get a signal subscription by ID

> Retrieve a single subscription merged with its signal template data.

```json
{"openapi":"3.2.0","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Signal Subscriptions","summary":"Signal Subscriptions","kind":"nav","description":"## Signal Subscriptions\n\nSubscriptions schedule recurring signal executions against a signal template.\nEach subscription ties a template to a frequency, timezone, and optional\ntargeting (list or domain).\n\n**Lifecycle:**\n1. Create a subscription via `POST /v1/companies/signals/subscriptions`\n   (references an existing template or creates one inline)\n2. Activate it with `POST /v1/companies/signals/{signalId}/start`\n3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`\n4. Pause with `POST /v1/companies/signals/{signalId}/stop`\n\nThe response merges the template definition with the schedule configuration\nso you get the full picture in a single object.\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":{"SignalSubscriptionResponse":{"type":"object","description":"A signal subscription merged with its template definition.","properties":{"id":{"type":"string","format":"uuid","description":"The subscription ID (unique per subscription)."},"signalTemplateId":{"type":"string","format":"uuid","description":"The signal template ID this subscription is based on. Use this to correlate subscriptions that share the same template."},"version":{"type":"integer","description":"Template version number"},"name":{"type":"string","description":"Subscription name if set, otherwise the template name"},"description":{"type":"string"},"question":{"type":"string","description":"The research question"},"answerType":{"type":"string","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"outputSchema":{"type":"object","additionalProperties":true},"weight":{"type":"string","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true},"frequency":{"type":"string","description":"Preset frequency if set","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"The resolved cron expression"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"status":{"type":"string","enum":["active","stopped"]},"listId":{"type":"string","format":"uuid","description":"Contact list ID"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","signalTemplateId","version","name","question","answerType","cronExpression","timezone","status","listId","source","createdAt"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by every endpoint that flows through the global error handler. Note: the global rate-limit middleware (HTTP 429 from per-API-key throttling) returns a different, flat shape — see `RateLimitErrorResponse`.\n","required":["error"],"properties":{"error":{"type":"object","required":["type","code","requestId"],"properties":{"type":{"type":"string","description":"Error category. Maps 1:1 to HTTP status (e.g. VALIDATION → 422, UNAUTHORIZED → 401).","enum":["BAD_REQUEST","VALIDATION","UNPROCESSABLE_ENTITY","NOT_FOUND","CONFLICT","UNAUTHORIZED","FORBIDDEN","PAYMENT_REQUIRED","PAYLOAD_TOO_LARGE","INTERNAL","EXTERNAL","TIMEOUT"]},"code":{"type":"string","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","description":"Human-readable error message. Wording may change; do not match against this string."},"errorCode":{"type":"string","description":"Optional public error code propagated from a downstream service (e.g. NestJS, LinkedIn)."},"errorAction":{"type":"string","description":"Optional user action guidance (e.g. \"reconnect Sales Navigator\")."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured fields forwarded from a downstream service. Shape depends on the source."},"requestId":{"type":"string","format":"uuid","description":"Correlation ID for this request. Include when reporting issues."},"fields":{"type":"array","description":"Per-field validation errors (populated when `type` is `VALIDATION` and the cause is a struct-tag validator).","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"debug":{"type":"object","description":"Debug information. Only present in development environments.","properties":{"cause":{"type":"string"}}}}}}}}},"paths":{"/v1/companies/signals/subscriptions/{subscriptionId}":{"get":{"summary":"Get a signal subscription by ID","description":"Retrieve a single subscription merged with its signal template data.","operationId":"getSignalSubscription","tags":["Signal Subscriptions"],"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/SignalSubscriptionResponse"}}}},"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"}}}}}}}}}
```

## Update a signal subscription

> Update a subscription's schedule configuration and/or its underlying template fields.\
> When schedule fields are provided, the active schedule is updated.\
> When template fields are provided, the underlying signal template is updated inline.<br>

```json
{"openapi":"3.2.0","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Signal Subscriptions","summary":"Signal Subscriptions","kind":"nav","description":"## Signal Subscriptions\n\nSubscriptions schedule recurring signal executions against a signal template.\nEach subscription ties a template to a frequency, timezone, and optional\ntargeting (list or domain).\n\n**Lifecycle:**\n1. Create a subscription via `POST /v1/companies/signals/subscriptions`\n   (references an existing template or creates one inline)\n2. Activate it with `POST /v1/companies/signals/{signalId}/start`\n3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`\n4. Pause with `POST /v1/companies/signals/{signalId}/stop`\n\nThe response merges the template definition with the schedule configuration\nso you get the full picture in a single object.\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":{"UpdateSignalSubscriptionRequest":{"type":"object","description":"Replace a subscription's full configuration.\nExactly one of `frequency` or `cronExpression` must be provided.\n","required":["timezone","name","question","answerType"],"properties":{"frequency":{"type":"string","description":"Preset schedule frequency. Mutually exclusive with `cronExpression`.\n","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"Custom cron expression (5-field). Mutually exclusive with `frequency`.\n"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"name":{"type":"string","description":"The subscription display name","minLength":1,"maxLength":200},"question":{"type":"string","description":"The research question","minLength":1,"maxLength":500},"answerType":{"type":"string","description":"Expected answer format","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"description":{"type":"string","description":"Signal description","maxLength":1000},"outputSchema":{"type":["object","null"],"additionalProperties":true,"description":"JSON schema for json_schema answer type. Send null to clear."},"weight":{"type":"string","description":"Signal importance weight","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true,"description":"Qualification criteria"}}},"SignalSubscriptionResponse":{"type":"object","description":"A signal subscription merged with its template definition.","properties":{"id":{"type":"string","format":"uuid","description":"The subscription ID (unique per subscription)."},"signalTemplateId":{"type":"string","format":"uuid","description":"The signal template ID this subscription is based on. Use this to correlate subscriptions that share the same template."},"version":{"type":"integer","description":"Template version number"},"name":{"type":"string","description":"Subscription name if set, otherwise the template name"},"description":{"type":"string"},"question":{"type":"string","description":"The research question"},"answerType":{"type":"string","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"outputSchema":{"type":"object","additionalProperties":true},"weight":{"type":"string","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true},"frequency":{"type":"string","description":"Preset frequency if set","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"The resolved cron expression"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"status":{"type":"string","enum":["active","stopped"]},"listId":{"type":"string","format":"uuid","description":"Contact list ID"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","signalTemplateId","version","name","question","answerType","cronExpression","timezone","status","listId","source","createdAt"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by every endpoint that flows through the global error handler. Note: the global rate-limit middleware (HTTP 429 from per-API-key throttling) returns a different, flat shape — see `RateLimitErrorResponse`.\n","required":["error"],"properties":{"error":{"type":"object","required":["type","code","requestId"],"properties":{"type":{"type":"string","description":"Error category. Maps 1:1 to HTTP status (e.g. VALIDATION → 422, UNAUTHORIZED → 401).","enum":["BAD_REQUEST","VALIDATION","UNPROCESSABLE_ENTITY","NOT_FOUND","CONFLICT","UNAUTHORIZED","FORBIDDEN","PAYMENT_REQUIRED","PAYLOAD_TOO_LARGE","INTERNAL","EXTERNAL","TIMEOUT"]},"code":{"type":"string","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","description":"Human-readable error message. Wording may change; do not match against this string."},"errorCode":{"type":"string","description":"Optional public error code propagated from a downstream service (e.g. NestJS, LinkedIn)."},"errorAction":{"type":"string","description":"Optional user action guidance (e.g. \"reconnect Sales Navigator\")."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured fields forwarded from a downstream service. Shape depends on the source."},"requestId":{"type":"string","format":"uuid","description":"Correlation ID for this request. Include when reporting issues."},"fields":{"type":"array","description":"Per-field validation errors (populated when `type` is `VALIDATION` and the cause is a struct-tag validator).","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"debug":{"type":"object","description":"Debug information. Only present in development environments.","properties":{"cause":{"type":"string"}}}}}}}}},"paths":{"/v1/companies/signals/subscriptions/{subscriptionId}":{"put":{"summary":"Update a signal subscription","description":"Update a subscription's schedule configuration and/or its underlying template fields.\nWhen schedule fields are provided, the active schedule is updated.\nWhen template fields are provided, the underlying signal template is updated inline.\n","operationId":"updateSignalSubscription","tags":["Signal Subscriptions"],"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/UpdateSignalSubscriptionRequest"}}}},"responses":{"200":{"description":"Subscription updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalSubscriptionResponse"}}}},"400":{"description":"Bad Request - Invalid parameters","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"}}}}}}}}}
```

## Start a signal subscription

> Activate a stopped subscription. Begins recurring signal execution\
> according to the subscription's cron expression.<br>

```json
{"openapi":"3.2.0","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Signal Subscriptions","summary":"Signal Subscriptions","kind":"nav","description":"## Signal Subscriptions\n\nSubscriptions schedule recurring signal executions against a signal template.\nEach subscription ties a template to a frequency, timezone, and optional\ntargeting (list or domain).\n\n**Lifecycle:**\n1. Create a subscription via `POST /v1/companies/signals/subscriptions`\n   (references an existing template or creates one inline)\n2. Activate it with `POST /v1/companies/signals/{signalId}/start`\n3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`\n4. Pause with `POST /v1/companies/signals/{signalId}/stop`\n\nThe response merges the template definition with the schedule configuration\nso you get the full picture in a single object.\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":{"SignalSubscriptionResponse":{"type":"object","description":"A signal subscription merged with its template definition.","properties":{"id":{"type":"string","format":"uuid","description":"The subscription ID (unique per subscription)."},"signalTemplateId":{"type":"string","format":"uuid","description":"The signal template ID this subscription is based on. Use this to correlate subscriptions that share the same template."},"version":{"type":"integer","description":"Template version number"},"name":{"type":"string","description":"Subscription name if set, otherwise the template name"},"description":{"type":"string"},"question":{"type":"string","description":"The research question"},"answerType":{"type":"string","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"outputSchema":{"type":"object","additionalProperties":true},"weight":{"type":"string","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true},"frequency":{"type":"string","description":"Preset frequency if set","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"The resolved cron expression"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"status":{"type":"string","enum":["active","stopped"]},"listId":{"type":"string","format":"uuid","description":"Contact list ID"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","signalTemplateId","version","name","question","answerType","cronExpression","timezone","status","listId","source","createdAt"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by every endpoint that flows through the global error handler. Note: the global rate-limit middleware (HTTP 429 from per-API-key throttling) returns a different, flat shape — see `RateLimitErrorResponse`.\n","required":["error"],"properties":{"error":{"type":"object","required":["type","code","requestId"],"properties":{"type":{"type":"string","description":"Error category. Maps 1:1 to HTTP status (e.g. VALIDATION → 422, UNAUTHORIZED → 401).","enum":["BAD_REQUEST","VALIDATION","UNPROCESSABLE_ENTITY","NOT_FOUND","CONFLICT","UNAUTHORIZED","FORBIDDEN","PAYMENT_REQUIRED","PAYLOAD_TOO_LARGE","INTERNAL","EXTERNAL","TIMEOUT"]},"code":{"type":"string","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","description":"Human-readable error message. Wording may change; do not match against this string."},"errorCode":{"type":"string","description":"Optional public error code propagated from a downstream service (e.g. NestJS, LinkedIn)."},"errorAction":{"type":"string","description":"Optional user action guidance (e.g. \"reconnect Sales Navigator\")."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured fields forwarded from a downstream service. Shape depends on the source."},"requestId":{"type":"string","format":"uuid","description":"Correlation ID for this request. Include when reporting issues."},"fields":{"type":"array","description":"Per-field validation errors (populated when `type` is `VALIDATION` and the cause is a struct-tag validator).","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"debug":{"type":"object","description":"Debug information. Only present in development environments.","properties":{"cause":{"type":"string"}}}}}}}}},"paths":{"/v1/companies/signals/subscriptions/{subscriptionId}/start":{"post":{"summary":"Start a signal subscription","description":"Activate a stopped subscription. Begins recurring signal execution\naccording to the subscription's cron expression.\n","operationId":"startSignalSubscription","tags":["Signal Subscriptions"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription to start","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Subscription started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalSubscriptionResponse"}}}},"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"}}}}}}}}}
```

## Stop a signal subscription

> Pause an active subscription so no further recurring executions occur.\
> The subscription can be restarted later.<br>

```json
{"openapi":"3.2.0","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Signal Subscriptions","summary":"Signal Subscriptions","kind":"nav","description":"## Signal Subscriptions\n\nSubscriptions schedule recurring signal executions against a signal template.\nEach subscription ties a template to a frequency, timezone, and optional\ntargeting (list or domain).\n\n**Lifecycle:**\n1. Create a subscription via `POST /v1/companies/signals/subscriptions`\n   (references an existing template or creates one inline)\n2. Activate it with `POST /v1/companies/signals/{signalId}/start`\n3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`\n4. Pause with `POST /v1/companies/signals/{signalId}/stop`\n\nThe response merges the template definition with the schedule configuration\nso you get the full picture in a single object.\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":{"SignalSubscriptionResponse":{"type":"object","description":"A signal subscription merged with its template definition.","properties":{"id":{"type":"string","format":"uuid","description":"The subscription ID (unique per subscription)."},"signalTemplateId":{"type":"string","format":"uuid","description":"The signal template ID this subscription is based on. Use this to correlate subscriptions that share the same template."},"version":{"type":"integer","description":"Template version number"},"name":{"type":"string","description":"Subscription name if set, otherwise the template name"},"description":{"type":"string"},"question":{"type":"string","description":"The research question"},"answerType":{"type":"string","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"outputSchema":{"type":"object","additionalProperties":true},"weight":{"type":"string","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true},"frequency":{"type":"string","description":"Preset frequency if set","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"The resolved cron expression"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"status":{"type":"string","enum":["active","stopped"]},"listId":{"type":"string","format":"uuid","description":"Contact list ID"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","signalTemplateId","version","name","question","answerType","cronExpression","timezone","status","listId","source","createdAt"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by every endpoint that flows through the global error handler. Note: the global rate-limit middleware (HTTP 429 from per-API-key throttling) returns a different, flat shape — see `RateLimitErrorResponse`.\n","required":["error"],"properties":{"error":{"type":"object","required":["type","code","requestId"],"properties":{"type":{"type":"string","description":"Error category. Maps 1:1 to HTTP status (e.g. VALIDATION → 422, UNAUTHORIZED → 401).","enum":["BAD_REQUEST","VALIDATION","UNPROCESSABLE_ENTITY","NOT_FOUND","CONFLICT","UNAUTHORIZED","FORBIDDEN","PAYMENT_REQUIRED","PAYLOAD_TOO_LARGE","INTERNAL","EXTERNAL","TIMEOUT"]},"code":{"type":"string","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","description":"Human-readable error message. Wording may change; do not match against this string."},"errorCode":{"type":"string","description":"Optional public error code propagated from a downstream service (e.g. NestJS, LinkedIn)."},"errorAction":{"type":"string","description":"Optional user action guidance (e.g. \"reconnect Sales Navigator\")."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured fields forwarded from a downstream service. Shape depends on the source."},"requestId":{"type":"string","format":"uuid","description":"Correlation ID for this request. Include when reporting issues."},"fields":{"type":"array","description":"Per-field validation errors (populated when `type` is `VALIDATION` and the cause is a struct-tag validator).","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"debug":{"type":"object","description":"Debug information. Only present in development environments.","properties":{"cause":{"type":"string"}}}}}}}}},"paths":{"/v1/companies/signals/subscriptions/{subscriptionId}/stop":{"post":{"summary":"Stop a signal subscription","description":"Pause an active subscription so no further recurring executions occur.\nThe subscription can be restarted later.\n","operationId":"stopSignalSubscription","tags":["Signal Subscriptions"],"parameters":[{"name":"subscriptionId","in":"path","required":true,"description":"The unique identifier of the subscription to stop","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Subscription stopped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalSubscriptionResponse"}}}},"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"}}}}}}}}}
```

## Trigger an immediate run of a signal subscription

> Trigger an immediate execution of the subscription regardless of the cron schedule.\
> Works for both active and stopped subscriptions.<br>

```json
{"openapi":"3.2.0","info":{"title":"Saber Platform API","version":"1.0.0"},"tags":[{"name":"Signal Subscriptions","summary":"Signal Subscriptions","kind":"nav","description":"## Signal Subscriptions\n\nSubscriptions schedule recurring signal executions against a signal template.\nEach subscription ties a template to a frequency, timezone, and optional\ntargeting (list or domain).\n\n**Lifecycle:**\n1. Create a subscription via `POST /v1/companies/signals/subscriptions`\n   (references an existing template or creates one inline)\n2. Activate it with `POST /v1/companies/signals/{signalId}/start`\n3. Optionally update schedule parameters via `PUT .../subscriptions/{id}`\n4. Pause with `POST /v1/companies/signals/{signalId}/stop`\n\nThe response merges the template definition with the schedule configuration\nso you get the full picture in a single object.\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":{"SignalSubscriptionResponse":{"type":"object","description":"A signal subscription merged with its template definition.","properties":{"id":{"type":"string","format":"uuid","description":"The subscription ID (unique per subscription)."},"signalTemplateId":{"type":"string","format":"uuid","description":"The signal template ID this subscription is based on. Use this to correlate subscriptions that share the same template."},"version":{"type":"integer","description":"Template version number"},"name":{"type":"string","description":"Subscription name if set, otherwise the template name"},"description":{"type":"string"},"question":{"type":"string","description":"The research question"},"answerType":{"type":"string","enum":["open_text","number","boolean","list","percentage","currency","url","contacts","contact_posts","contact_engagements","json_schema"]},"outputSchema":{"type":"object","additionalProperties":true},"weight":{"type":"string","enum":["important","nice_to_have","not_important"]},"qualificationCriteria":{"type":"object","additionalProperties":true},"frequency":{"type":"string","description":"Preset frequency if set","enum":["daily","weekly","monthly"]},"cronExpression":{"type":"string","description":"The resolved cron expression"},"timezone":{"type":"string","description":"IANA timezone for scheduling"},"status":{"type":"string","enum":["active","stopped"]},"listId":{"type":"string","format":"uuid","description":"Contact list ID"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","signalTemplateId","version","name","question","answerType","cronExpression","timezone","status","listId","source","createdAt"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by every endpoint that flows through the global error handler. Note: the global rate-limit middleware (HTTP 429 from per-API-key throttling) returns a different, flat shape — see `RateLimitErrorResponse`.\n","required":["error"],"properties":{"error":{"type":"object","required":["type","code","requestId"],"properties":{"type":{"type":"string","description":"Error category. Maps 1:1 to HTTP status (e.g. VALIDATION → 422, UNAUTHORIZED → 401).","enum":["BAD_REQUEST","VALIDATION","UNPROCESSABLE_ENTITY","NOT_FOUND","CONFLICT","UNAUTHORIZED","FORBIDDEN","PAYMENT_REQUIRED","PAYLOAD_TOO_LARGE","INTERNAL","EXTERNAL","TIMEOUT"]},"code":{"type":"string","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","description":"Human-readable error message. Wording may change; do not match against this string."},"errorCode":{"type":"string","description":"Optional public error code propagated from a downstream service (e.g. NestJS, LinkedIn)."},"errorAction":{"type":"string","description":"Optional user action guidance (e.g. \"reconnect Sales Navigator\")."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured fields forwarded from a downstream service. Shape depends on the source."},"requestId":{"type":"string","format":"uuid","description":"Correlation ID for this request. Include when reporting issues."},"fields":{"type":"array","description":"Per-field validation errors (populated when `type` is `VALIDATION` and the cause is a struct-tag validator).","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}},"debug":{"type":"object","description":"Debug information. Only present in development environments.","properties":{"cause":{"type":"string"}}}}}}}}},"paths":{"/v1/companies/signals/subscriptions/{subscriptionId}/trigger":{"post":{"summary":"Trigger an immediate run of a signal subscription","description":"Trigger an immediate execution of the subscription regardless of the cron schedule.\nWorks for both active and stopped subscriptions.\n","operationId":"triggerSignalSubscription","tags":["Signal Subscriptions"],"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/SignalSubscriptionResponse"}}}},"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"}}}}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.saber.app/signal-subscriptions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
