> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Subscribe several accounts to a trigger (beta)

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

This endpoint is in beta. Its request and response may change.

Subscribes up to 100 connected accounts to one trigger with the same filters, and returns a result for each account. An account that can't subscribe doesn't stop the others: its result is `REFUSED`, `NOT_FOUND` or `FAILED`, with a `reason`. Retrying the request is safe; an account subscribed earlier comes back as `ALREADY_SUBSCRIBED`. For a per-connection trigger, send an empty `connected_account_ids`.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `connection_id` | string | Yes | ID of the connection, in this environment. Up to 64 characters. |

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `trigger_name` | string | Yes | Name of the trigger to subscribe to, as returned in the name field of [List available triggers](https://docs.scalekit.com/agentkit/reference/triggers/list-available-triggers/). Up to 128 characters. |
| `config` | object | No | Filter values applied to every account in the batch, keyed by the trigger's config_fields keys. Each account gets its own subscription with these values, so subscribing the same accounts again with different values adds subscriptions rather than replacing these. Invalid values refuse the whole request. |
| `connected_account_ids` | array of string | No | Connected accounts to subscribe, at most 100 — one page of the account picker — with no repeats. Which to send depends on the trigger's delivery_scope, from [List available triggers](https://docs.scalekit.com/agentkit/reference/triggers/list-available-triggers/). For an ACCOUNT-scoped trigger, list at least one account; an empty list refuses the whole request with a 400. For a CONNECTION-scoped trigger, send an empty list: the trigger is subscribed once, on the connection itself, and results holds exactly one result, with an empty connected_account_id. Naming accounts for a connection-scoped trigger refuses each of them (REFUSED), since that trigger is not subscribed per account. |
| `interval_seconds` | integer | No | Polling interval in seconds, for a polled trigger only, applied to every account in the batch. Omit it to use the trigger's default_interval_seconds. A value below the trigger's min_interval_seconds, or any value for a webhook trigger, refuses the whole request. A large batch of polled subscriptions shares the environment's polling budget, so the subscriptions can run slower than requested; effective_interval_seconds on each subscription shows the interval it runs at. |

**Response (200)**

| Name | Type | Description |
| --- | --- | --- |
| `created_count` | integer | How many subscriptions this call created. Excludes accounts that were already subscribed. |
| `results` | array of object | One result per requested account, in the order the accounts were sent, so a client can pair them up positionally without matching on id. For a connection-scoped trigger subscribed with an empty connected_account_ids, exactly one result, with an empty connected_account_id. |
| `results.connected_account_id` | string | The connected account ID this result is for, as sent in the request. |
| `results.outcome` | string (enum) | What happened to this account. CREATED — a subscription was created. ALREADY_SUBSCRIBED — the account already had a subscription to this trigger with these exact config values; nothing new was created, and list subscriptions to read the existing one. REFUSED — the account cannot receive this trigger; reason says why and what to do. NOT_FOUND — no such account on this connection in this environment. FAILED — the attempt failed for a reason unrelated to the account; nothing was created, and retrying may succeed. One of: `CREATED`, `ALREADY_SUBSCRIBED`, `REFUSED`, `NOT_FOUND`, `FAILED`. |
| `results.reason` | string | Why the account was not subscribed, and for a refusal what to do about it, in one sentence — the same text [Subscribe to a trigger](https://docs.scalekit.com/agentkit/reference/triggers/create-a-trigger-subscription/) returns for the same account. Empty for CREATED. |
| `results.subscription` | object | The created subscription, for CREATED. Absent for every other outcome, including ALREADY_SUBSCRIBED. |
| `results.subscription.account_health` | string (enum) | How the subscribed account stands for this trigger. AWAITING_CONFIRMATION means Scalekit cannot route this trigger's events to the account yet, so the subscription will not fire until the account's user reconnects it. Absent for connection-scoped subscriptions. One of: `READY`, `AWAITING_CONFIRMATION`, `WRONG_APP`, `DISCONNECTED`, `NEEDS_REAUTHENTICATION`. |
| `results.subscription.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. |
| `results.subscription.connected_account_id` | string | ID of the subscribed connected account. Empty for a connection-scoped subscription. |
| `results.subscription.connected_account_identifier` | string | The identifier the connected account was created with, your app's ID for the user, such as `user_123`, so you can label the subscription without fetching each account. 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. |
| `results.subscription.connection_id` | string | ID of the connection the subscription belongs to. |
| `results.subscription.created_at` | string | When the subscription was created. Returned so a list can be ordered or explained by age without a second lookup. |
| `results.subscription.delivery_scope` | string (enum) | Whether this subscription receives one event per connected account or one event for the whole connection. A connection-scoped subscription carries no connected_account_id — the connection is the only recipient. One of: `ACCOUNT`, `CONNECTION`. |
| `results.subscription.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. |
| `results.subscription.id` | string | Unique identifier of the trigger subscription. |
| `results.subscription.poll_state` | object | How a POLL subscription's feed is doing: when it last ran, why the last run failed, and whether polling is held off. Absent for a WEBHOOK subscription, which is never polled. |
| `results.subscription.provider` | string | The provider the trigger belongs to. |
| `results.subscription.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. |
| `results.subscription.status` | string (enum) | Whether the subscription is delivering. ACTIVE — delivering. THROTTLED — delivering, but polling slower than requested; compare requested_interval_seconds with effective_interval_seconds. PAUSED — stopped by you. PAUSED_CREDENTIAL — stopped because the account's credential no longer works. One of: `ACTIVE`, `THROTTLED`, `PAUSED`, `PAUSED_CREDENTIAL`. |
| `results.subscription.trigger_name` | string | Name of the subscribed trigger, as returned by [List available triggers](https://docs.scalekit.com/agentkit/reference/triggers/list-available-triggers/). |

**Errors**

- `400`: Invalid request, nothing created - connection_id or an entry of connected_account_ids is malformed; config is invalid for this trigger; interval_seconds is below the trigger's minimum, or is set for a webhook trigger; the trigger polls and is connection-scoped, which is not supported; or connected_account_ids is empty for a trigger that is subscribed per connected account. A well-formed ID naming an account that does not exist is not this case: it comes back as a per-account NOT_FOUND result with a 200, so one bad ID in a batch of a hundred does not discard the ninety-nine that would have succeeded
- `404`: Not found - the connection does not exist in this environment, the connection's provider publishes no trigger with this name, or Triggers isn't turned on for your environment
- `500`: Internal error - the connection or the trigger's definition could not be read, so no account was processed; retry the request

**Request**

```bash
curl -sS -X POST \
  "$SCALEKIT_ENVIRONMENT_URL/api/v1/connections/conn_133400101014995480/trigger-subscriptions:batchCreate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger_name": "salesforce_lead_created",
    "connected_account_ids": [
      "ca_133400349586228019",
      "ca_133400349586231107"
    ],
    "config": {
      "lead_source": "Web"
    },
    "interval_seconds": 300
  }'
```

**Response**

```json
{
  "results": [
    {
      "connected_account_id": "ca_133400349586228019",
      "outcome": "ALREADY_SUBSCRIBED",
      "reason": "this principal already has a subscription to this trigger with these exact settings"
    },
    {
      "connected_account_id": "ca_133400349586231107",
      "outcome": "CREATED",
      "reason": "",
      "subscription": {
        "id": "trgs_141020933185736602",
        "connected_account_id": "ca_133400349586231107",
        "connected_account_identifier": "user_456",
        "connection_id": "conn_133400101014995480",
        "provider": "salesforce",
        "trigger_name": "salesforce_lead_created",
        "status": "ACTIVE",
        "delivery_scope": "ACCOUNT",
        "requested_interval_seconds": 300,
        "effective_interval_seconds": 300,
        "config": {
          "lead_source": "Web"
        },
        "created_at": "2026-10-28T09:20:02.480Z",
        "poll_state": {
          "last_error": "",
          "last_error_code": "TRIGGER_POLL_ERROR_CODE_UNSPECIFIED",
          "consecutive_failures": 0,
          "watermark_updated_at": "2026-10-28T09:20:02.480Z"
        },
        "account_health": "READY"
      }
    }
  ],
  "created_count": 1
}
```

**Python SDK:** `scalekit_client.actions.triggers.batch_create_subscriptions`

Subscribe up to 100 connected accounts to a trigger in one call. Not atomic: each account gets its own outcome in `results` (`CREATED`, `ALREADY_SUBSCRIBED`, `REFUSED`, `NOT_FOUND`, `FAILED`), and those never raise. Safe to call again for the `FAILED` ones. For a connection-scoped trigger, leave `connected_account_ids` out.

```python
scalekit_client.actions.triggers.batch_create_subscriptions(
    connection_id: str,
    trigger_name: str,
    connected_account_ids: Sequence[str] | None = None,
    interval: timedelta | None = None,
    config: Mapping[str, str] | None = None,
) -> BatchCreateTriggerSubscriptionsResponse
```

Example:

```python
from datetime import timedelta

result = scalekit_client.actions.triggers.batch_create_subscriptions(
    connection_id="conn_133400101014995480",
    trigger_name="salesforce_lead_created",
    connected_account_ids=["ca_133400349586228019", "ca_133400349586231107"],
    interval=timedelta(minutes=5),
    config={"lead_source": "Web"},
)
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `connection_id` | `str` | Yes | The connection (`conn_...`). |
| `trigger_name` | `str` | Yes | `AvailableTrigger.name`. |
| `connected_account_ids` | `Sequence[str] \| None` | No | The accounts (`ca_...`), unique. |
| `interval` | `timedelta \| None` | No | Poll interval, in whole seconds (see `create_subscription`). |
| `config` | `Mapping[str, str] \| None` | No | Values for the trigger's `config_fields`. |

Returns `BatchCreateTriggerSubscriptionsResponse`: Per-account results and `created_count`.


Part of [Triggers](https://docs.scalekit.com/agentkit/reference/triggers/) in the [AgentKit API reference](https://docs.scalekit.com/agentkit/reference/). Authentication: https://docs.scalekit.com/agentkit/reference/authentication.md. Errors and rate limits: https://docs.scalekit.com/agentkit/reference/errors.md. Pagination: https://docs.scalekit.com/agentkit/reference/pagination.md


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
