# Check whether a campaign can send

`GET /v1/campaigns/{id}/eligibility`

Requires an API key with the `campaigns:read` scope. [About keys and scopes](/docs/api/authentication)

Reports every blocker that would stop this campaign sending — unverified domain, empty audience, invalid content — without attempting a send. Campaign-wide blockers sit at the top; each selected channel reports its own reach and blockers. Sending is all or nothing, so one blocked channel sets every channel's `sendableRecipientCount` to 0. Call this before sending to turn a 409 into an actionable list. This is an estimate: it neither reserves quota nor guarantees delivery.

## Path parameters

- `id` (string, required, uuid)

## Returns

Returns `200 OK` with a `CampaignEligibility` in `data`. Otherwise returns an error; [Errors](/docs/api/errors) lists every code and which to retry.

- `campaignId` (string | null, required, uuid) — `null` when checked before saving (`POST /campaigns/eligibility`).
- `checkedAt` (string, required, date-time) — When the check ran.
- `audienceCount` (integer, required, min 0, max 9007199254740991) — Contacts in the audience, before any channel's exclusions.
- `blockers` (string[], required) — Blockers for the campaign as a whole.
- `issues` (object[], required) — What the draft still lacks, exactly as sending would refuse it (`DRAFT_INCOMPLETE`).
  - `path` (string, required) — The field that is incomplete, such as `content.email`.
  - `message` (string, required) — What is missing, in plain words.
- `channels` (object[], required) — One entry per selected channel.
  - One of: **Email channel**
    - `channel` ("email", required)
    - `eligibleRecipientCount` (integer, required, min 0, max 9007199254740991) — Contacts reachable on this channel after the exclusions.
    - `sendableRecipientCount` (integer, required, min 0, max 9007199254740991) — `eligibleRecipientCount` when nothing blocks the campaign anywhere, else 0.
    - `blockers` (string[], required) — What stops the email channel sending.
    - `excluded` (object, required) — Contacts left out of the audience, by reason.
      - `consentMissing` (integer, required, min 0, max 9007199254740991) — Contacts without email consent.
      - `topicUnsubscribed` (integer, required, min 0, max 9007199254740991) — Consented, but the campaign's topic does not reach them.
      - `suppressed` (integer, required, min 0, max 9007199254740991) — Contacts whose address is blocked, for example after a bounce.
      - `missingEmail` (integer, required, min 0, max 9007199254740991) — Contacts with no email address.
    - `senderVerified` (boolean, required) — Whether the sender domain is verified.
  - One of: **Push channel**
    - `channel` ("push", required)
    - `eligibleRecipientCount` (integer, required, min 0, max 9007199254740991) — Contacts reachable on this channel after the exclusions.
    - `sendableRecipientCount` (integer, required, min 0, max 9007199254740991) — `eligibleRecipientCount` when nothing blocks the campaign anywhere, else 0.
    - `blockers` (string[], required) — What stops the push channel sending.
    - `excluded` (object, required) — Contacts left out of the audience, by reason.
      - `consentMissing` (integer, required, min 0, max 9007199254740991) — Contacts without push consent.
      - `topicUnsubscribed` (integer, required, min 0, max 9007199254740991) — Consented, but the campaign's topic does not reach them.
      - `suppressed` (integer, required, min 0, max 9007199254740991) — Contacts blocked from push.
      - `missingInstallation` (integer, required, min 0, max 9007199254740991) — Contacts with no registered device.
    - `applicationReady` (boolean, required) — Whether the push app is set up to send.

## Example

```bash
curl https://api.kirora.io/v1/campaigns/018f2a4e-6b1c-7d3e-9f40-37386ae05a6b/eligibility \
  -H "Authorization: Bearer $KIRORA_API_KEY"
```

Response `200`:

```json
{
  "data": {
    "campaignId": "018f2a4e-6b1c-7d3e-9f40-3478765e5a6b",
    "checkedAt": "2030-03-14T09:30:00Z",
    "audienceCount": 0,
    "blockers": [
      "campaign_not_draft"
    ],
    "issues": [
      {
        "path": "path_example",
        "message": "message_example"
      }
    ],
    "channels": [
      {
        "channel": "email",
        "eligibleRecipientCount": 0,
        "sendableRecipientCount": 0,
        "blockers": [
          "missing_email_content"
        ],
        "excluded": {
          "consentMissing": 0,
          "topicUnsubscribed": 0,
          "suppressed": 0,
          "missingEmail": 0
        },
        "senderVerified": true
      }
    ]
  }
}
```
