---
title: "Create an internal Telegram campaign for existing private chats"
method: POST
path: "/campaigns"
---

# Create an internal Telegram campaign for existing private chats

`POST /campaigns`

## Request

- Base URL: `https://gramclaw.com/api/v1`
- URL: `https://gramclaw.com/api/v1/campaigns`
- Auth: HTTP bearer

Requires an explicitly issued campaign-scoped key, the REST, Campaigns, scoped-routing and independent campaign-mutation feature gates, the exact campaign user allowlist, the exact campaign workspace allowlist, and Idempotency-Key (bound to this exact payload). Recipients must be existing private chats of READY internal Telegram accounts in the key workspace (max 100; duplicates collapse). No @username resolution, attachments, client-supplied names, broadcasts, or Unipile fallback. Names/usernames for personalization come from Telegram. Suppressed recipients reject the whole request. Campaign, steps and recipients are written in one database transaction; this endpoint never sends a message — the durable worker dispatches queued recipients. Ambiguous outcomes are never retried.

## Headers

- `Idempotency-Key` string, required

## Request body

- CreateCampaignRequest
  - `name` string
  - `message_text` string, required: Supports [[name]] and [[username]], resolved from Telegram for every recipient.
  - `recipients` object[], required
    - `account_id` string, required
    - `chat_id` string, required
  - `steps` object[]: Follow-ups. Without branching every step uses branch no_reply (max 5); with branching each step is seen or unseen (max 5 per track).
    - `branch` 'no_reply' | 'seen' | 'unseen', required
    - `wait_hours` number, required
    - `variants` string[], required
  - `branching_enabled` boolean: Seen/unseen branching; rejected unless the independent U4 branching and read-receipt gates are on.
  - `daily_quota_per_account` integer
  - `max_followups` integer
  - `scheduled_at` string, date-time: Not in the past; at most one year ahead.
  - `schedule_timezone` string: IANA time zone, default UTC.

## Response `200`

Existing campaign for this operation (idempotent)

## Other responses

- `201`: Campaign created and queued for the worker; nothing was sent
- `400`: Invalid or unsupported input, suppressed recipients, unresolved personalization, missing Idempotency-Key, or disabled branching
- `403`: Missing campaign scope, user/workspace allowlist, or account ownership
- `404`: Recipient chat not found for the account
- `409`: Idempotency collision, in-flight or ambiguous prior operation, or sending account no longer READY
- `429`: Campaign creation rate limit
- `503`: Feature disabled, U5d2 migration not installed, suppression list unavailable, or outcome unknown (do not retry)

---

[API](https://skmtc.dev/gramclaw/apis/gramclaw-telegram-api.md) · [All operations](https://skmtc.dev/gramclaw/apis/gramclaw-telegram-api/llms.txt) · [OpenAPI document](https://skmtc.dev/gramclaw/apis/gramclaw-telegram-api/revisions/7506dc9c905a?raw)
