---
title: "Subscribe to a trigger"
method: POST
path: "/api/v1/connections/{connection_id}/trigger-subscriptions"
tags: ["Triggers"]
---

# Subscribe to a trigger

`POST /api/v1/connections/{connection_id}/trigger-subscriptions`

## Request

- Base URL: `https://$SCALEKIT_ENVIRONMENT_URL`
- URL: `https://$SCALEKIT_ENVIRONMENT_URL/api/v1/connections/{connection_id}/trigger-subscriptions`
- Auth: OAuth 2
  - Client credentials
  - Token URL: `https://$SCALEKIT_ENVIRONMENT_URL/oauth/token`
- TypeScript: <https://skmtc.dev/scalekit/apis/scalekit-api-reference/docs/api/v1/connections/:connection_id/trigger-subscriptions/post.ts> (a function with typed inputs; its response is checked against the schema)

Creates a subscription to one trigger, either for one connected account or for the whole connection. Use this endpoint after ListAvailableTriggers and ListEligibleAccounts have shown that the trigger and account can be used. Pass the connection ID in the path, and trigger_name in the body. For an account-scoped trigger, pass connected_account_id; for a connection-scoped trigger, omit it. Use config to set the trigger's filter values, with keys spelled exactly as the trigger's config_fields declare them. For a polled trigger, interval_seconds sets the polling interval, and defaults to the trigger's default interval. An interval below the trigger's minimum is refused, not rounded up. Each refusal says what to change, for example the missing scope, the minimum interval, or that the account was authorized under a different app. Returns the new subscription with its status, its requested and effective intervals, and the account's health for this trigger.

## Path parameters

- `connection_id` string, required

## Request body

- TriggerServiceCreateTriggerSubscriptionBody
  - `config` object: Filter values for the subscription, keyed by the trigger's config_fields keys, spelled exactly as returned. Every required field must be set. An unknown key, or a value longer than 512 characters, is refused. Subscribing again with different values creates another subscription; subscribing again with identical values returns 409.
  - `connected_account_id` string: Connected account to subscribe on, for an account-scoped trigger. Omit it for a connection-scoped trigger — the trigger is then subscribed on the connection itself and no account is named. Whether omitting it is valid depends on the trigger's own delivery_scope.
  - `interval_seconds` integer: Polling interval in seconds, for a polled trigger only. Omit it to use the trigger's default_interval_seconds. A value below the trigger's min_interval_seconds is refused, naming the minimum, rather than rounded up. Setting it for a webhook trigger is refused. The subscription can run slower than requested when the environment's polling budget is shared across many polled subscriptions; effective_interval_seconds on the response shows the interval it runs at.
  - `trigger_name` string, required: Name of the trigger to subscribe to, as returned in the name field of ListAvailableTriggers. Up to 128 characters.

## Response `200`

The created subscription, including its status, intervals, filter values and the subscribed account's health

- TriggersTriggerSubscription: A subscription of one connected account, or of a whole connection, to one trigger.
  - `account_health` 'READY' | 'AWAITING_CONFIRMATION' | 'WRONG_APP' | 'DISCONNECTED' | 'NEEDS_REAUTHENTICATION': A connected account's own state, evaluated for what the trigger in question routes by: a webhook trigger needs the provider workspace captured, and an account-scoped webhook trigger the provider user too. - READY: The account can receive triggers. - AWAITING_CONFIRMATION: Connected and working, but Scalekit has not confirmed which provider workspace or user it belongs to, so inbound events cannot be routed to it. - WRONG_APP: Authorized under a different OAuth app than the connection now uses. - DISCONNECTED: The account was disconnected. - NEEDS_REAUTHENTICATION: The credential itself is unusable: it has expired, or the account has not finished connecting.
  - `config` object: The subscription's filter values, keyed by the trigger's config_fields keys. Keys are returned exactly as stored; send them back without changing their case.
  - `connected_account_id` string: ID of the subscribed connected account. Empty for a connection-scoped subscription.
  - `connected_account_identifier` string: The identifier the connected account was created with, such as your app's user ID or the user's email address, so a client can label the subscription without fetching every account separately. Empty for a connection-scoped subscription, and empty when the account has no identifier recorded — fall back to connected_account_id rather than showing a blank.
  - `connection_id` string: ID of the connection the subscription belongs to.
  - `created_at` string, date-time: When the subscription was created. Returned so a list can be ordered or explained by age without a second lookup.
  - `delivery_scope` 'ACCOUNT' | 'CONNECTION': Whether a trigger delivers once per connected account or once for the whole connection. Set by the trigger, not chosen by the subscriber. A polled trigger polls with one connected account's credential, so a polled trigger that is connection-scoped is reported as unavailable. - ACCOUNT: One event per subscribed connected account. For a webhook trigger, an event is delivered for an account only when the event's provider workspace and user match the account's; a polled trigger polls each account with that account's own credential. Subscribed on a specific connected account. - CONNECTION: One event for the whole connection, whatever accounts exist on it. Subscribed on the connection itself, naming no account.
  - `effective_interval_seconds` integer: The polling interval, in seconds, the subscription actually runs at. Larger than requested_interval_seconds when the environment's polling budget is shared across many polled subscriptions; the subscription's status is then THROTTLED. Zero for a webhook trigger.
  - `id` string: Unique identifier of the trigger subscription.
  - `poll_state` TriggersTriggerPollState: The state of a poll subscription's feed, as of its most recent run. Read from the feed's own stored state on every request rather than derived, so a feed that is failing, rate limited, or held off is visible without looking at logs. A subscription whose status is ACTIVE can still be failing every run; this is where that shows.
    - `backoff_until` string, date-time: Polling is held off until this time, because the provider asked Scalekit to slow down or a run failed in a way retrying cannot fix. Absent when no hold-off has been recorded. A time in the past means the hold-off has ended and the next scheduled run polls again.
    - `consecutive_failures` integer: How many runs in a row have failed. Zero after any successful run.
    - `last_error` string: A short, human-readable explanation of why the most recent run failed and what happens next. Empty when the most recent run succeeded or no run has happened yet. Chosen from a fixed set of messages by last_error_code and never contains the provider's response. The wording can change: match on last_error_code, not on this text.
    - `last_error_code` 'RATE_LIMITED' | 'CREDENTIAL_REVOKED' | 'INVALID_CONFIGURATION' | 'PROVIDER_ERROR' | 'DELIVERY_FAILED' | 'TIMED_OUT' | 'POLL_FAILED': Why a poll subscription's most recent run failed. - RATE_LIMITED: The provider asked Scalekit to slow down. Polling resumes after backoff_until. - CREDENTIAL_REVOKED: The connected account's authorization was revoked or has expired. Reconnect the account. - INVALID_CONFIGURATION: The subscription's configuration does not produce a valid request for this trigger. Update the subscription's configuration. - PROVIDER_ERROR: The provider returned an error. Retried on the next run. - DELIVERY_FAILED: Events could not be handed to the delivery service. Retried on the next run. - TIMED_OUT: The run timed out before it finished. Retried on the next run. - POLL_FAILED: The run failed for a reason none of the other codes describes. Retried on the next run.
    - `last_run_at` string, date-time: When Scalekit last polled the provider for this subscription, whether or not the run succeeded. Absent until the first run. A value far older than the effective interval means the feed has stopped running.
    - `watermark_updated_at` string, date-time: When the feed's position last moved forward — the last time a run found and delivered newer events. A run that finds nothing new leaves it unchanged.
  - `provider` string: The provider the trigger belongs to.
  - `requested_interval_seconds` integer: The polling interval, in seconds, the subscription asked for, or the trigger's default when it did not set one. Returned next to effective_interval_seconds so a subscription running slower than requested is visible. Zero for a webhook trigger.
  - `status` 'ACTIVE' | 'THROTTLED' | 'PAUSED' | 'PAUSED_CREDENTIAL': Why a subscription is or is not currently delivering. - ACTIVE: Delivering. For a polled trigger, at the requested interval. - THROTTLED: Running slower than requested, not stopped. Still delivering. - PAUSED: Stopped by the customer. - PAUSED_CREDENTIAL: Stopped because the account's credential no longer works. Distinct from PAUSED so the two have distinguishable explanations for missing events.
  - `trigger_name` string: Name of the subscribed trigger, as returned by ListAvailableTriggers.

## Other responses

- `400`: Invalid request - the message names what to change. Returned when an ID is malformed; config holds an unknown key, misses a required key, or holds a value longer than 512 characters; interval_seconds is below the trigger's minimum, or is set for a webhook trigger; connected_account_id is missing for an account-scoped trigger, or present for a connection-scoped one; the trigger polls and is connection-scoped, which is not supported; or the account cannot receive the trigger because its grant lacks a required scope or the bot install the trigger needs, it was authorized under a different app, the trigger needs your own provider app, its provider workspace or user is not yet confirmed, or it holds no usable credential
- `404`: Not found - the connection or connected account does not exist in this environment, the connected account belongs to a different connection, the connection's provider publishes no trigger with this name, or Triggers is not enabled for the environment
- `409`: Conflict - this account, or this connection for a connection-scoped trigger, already has a subscription to this trigger with exactly these config values
- `500`: Internal error - the subscription could not be created; nothing was created
- `503`: Service unavailable - polling for the new subscription could not be scheduled, so the subscription was not created; retry the same request

## Changes

- **2026-10-30** `f47f1022d844`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/scalekit/apis/scalekit-api-reference/changes/api/v1/connections/:connection_id/trigger-subscriptions/post.md)

---

[API](https://skmtc.dev/scalekit/apis/scalekit-api-reference.md) - [All operations](https://skmtc.dev/scalekit/apis/scalekit-api-reference/llms.txt) - [OpenAPI document](https://skmtc.dev/scalekit/apis/scalekit-api-reference/revisions/f47f1022d844?raw)
