> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sequenzy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create an In-App Campaign

> Create an in-app campaign draft

Creates an in-app campaign draft: one in-app message or content card for an audience. You can set the message, priority, end time and audience now or later with [Update an In-App Campaign](https://docs.sequenzy.com/api-reference/in-app/update-campaign.md), then launch it with [Launch an In-App Campaign](https://docs.sequenzy.com/api-reference/in-app/send-campaign.md). Requires the `campaigns:write` scope.

## Request

**name** `string` (default: Untitled in-app campaign)

Campaign name, up to 255 characters.

**message** `object`

The message, with the same fields as an [in-app sequence step](https://docs.sequenzy.com/concepts/in-app-messages.md): `kind` (`message` or `card`), `format` (`modal`, `banner`, `fullscreen` or `html`), `position`, `eyebrow`, `title`, `body`, `imageUrl`, `imagePlacement`, `buttons` (up to two, each with `label`, `action` and `url`), `data`, `style`, `pinned`, `expiresAfterDays`, `html` and `showCloseButton`. Merge tags such as `{{firstName}}` are filled for each contact when their app receives it. `expiresAfterDays` limits how long a contact keeps it after receiving it; without it, the item stays until the campaign ends or the contact dismisses it.

**priority** `string` (default: medium)

`low`, `medium` or `high`. Apps show one message at a time; when several are waiting, higher priority comes first. Sequence messages count as `medium`.

**endsAt** `string | null`

ISO 8601 time the campaign ends. After it, nobody new gets the campaign and it leaves every feed that still has it, including cards contacts have seen but not dismissed. `null` means it runs until stopped.

**targetLists** `object`

Audience, the same shape as campaign `targetLists`: `{"type":"all"}`, `{"type":"lists","listIds":[...]}`, `{"type":"segment","segmentId":"..."}` or `{"type":"rules","include":[...],"exclude":[...]}`. Email status doesn't matter. Each contact is checked when their app fetches its feed while the campaign is live.

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/in-app/campaigns" \
  --header "Authorization: Bearer $SEQUENZY_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"name": "New dashboards", "message": {"kind": "message", "format": "modal", "title": "Hi {{firstName}}, dashboards are here", "buttons": [{"label": "Take a look", "url": "myapp://dashboards"}]}, "priority": "high", "targetLists": {"type": "segment", "segmentId": "seg_123"}}'
```

## Responses

```json 201 theme={null}
{
  "success": true,
  "campaign": {
    "id": "cmp_abc123",
    "name": "New dashboards",
    "type": "in_app",
    "status": "draft",
    "state": "draft",
    "message": {
      "label": "",
      "kind": "message",
      "format": "modal",
      "title": "Hi {{firstName}}, dashboards are here",
      "body": "See every campaign at a glance.",
      "buttons": [
        {
          "label": "Take a look",
          "action": "open_url",
          "url": "myapp://dashboards"
        }
      ]
    },
    "priority": "high",
    "endsAt": "2026-12-01T00:00:00.000Z",
    "targetLists": {
      "type": "segment",
      "segmentId": "seg_123"
    },
    "scheduledAt": null,
    "sentAt": null,
    "estimatedRecipientCount": null,
    "labelIds": [],
    "createdAt": "2026-11-07T12:00:00.000Z",
    "updatedAt": "2026-11-08T09:00:00.000Z"
  }
}
```

```json 400 theme={null}
{
  "error": "message.buttons.0.url: Use an https:// URL, an app deep link (myapp://...), or a merge tag"
}
```

```json 401 theme={null}
{
  "error": "Invalid API key"
}
```

```json 403 theme={null}
{
  "error": "API key is missing required scope: campaigns:write"
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.