# Channel readiness

The same readiness report narrowed to SMS or RCS: the channel's own setup steps, the countries a sender still ought to be registered for, and the countries it can actually send to right now.

**Language:** en
**Audience:** developer
**TLDR:** GET /v1/project/{project}/readiness/channel/{sms|rcs} returns steps (add-sender / add-agent, register-country, first send), one warning (recommended-registrations — countries a sender should be registered for and is not, only once the channel has an active sender) and reach: the countries you can send to now, with a per-sender breakdown, senderCount and defaultSender. On this scope operational also requires a non-empty reach: clearing every blocker is not the same as being able to deliver. What a carrier or regulator DID to a registration — pending-review, rejected-registration — is not here: it moved to GET /project/{project}/attention on 2026-09-05.
**Search keywords:** channel readiness, sms readiness, rcs readiness, which countries can I send to, reachable countries, coverage, sender registration, register a country, recommended registrations, warnings, add sender, add agent, default sender, senderCount, regulation, can I send to Spain, no coverage, operational, where did pending-review go, where did rejected-registration go
**Related pages:** /developers/product-api/project-setup/readiness, /developers/product-api/project-setup/attention
**Docs index (every page):** https://docs.instasent.com/llms.txt
**This zone's index:** https://docs.instasent.com/developers/product-api/llms-full.txt
**This page:** https://docs.instasent.com/developers/product-api/project-setup/channel-readiness/ (HTML) · https://docs.instasent.com/developers/product-api/project-setup/channel-readiness.md (Markdown)

The [project report](/developers/product-api/project-setup/readiness) answers "is this project set up". This one answers the two questions you actually ask before sending on a channel: **what is still missing here**, and **who can I reach right now**.

It returns the same object, with `scope: "channel"`, and fills in the two fields the project scope always leaves empty: `warnings` and `reach`.

What it does **not** answer is what a carrier or a regulator did to a registration you already submitted. That moved out on 2026-09-05 — see [What moved to the attention endpoint](#what-moved-to-the-attention-endpoint).

[`GET /v1/project/{project}/readiness/channel/{channel}` - Setup steps, the recommended-registrations warning and real send reach for one channel.](/developers/product-api/reference)

`channel` is `sms` or `rcs`. Any other value returns `404` — it is a route constraint, not a validation error, so don't expect a field-level message back.

```bash
curl "https://api.instasent.com/v1/project/$INSTASENT_PROJECT/readiness/channel/sms" \
  -H "Authorization: Bearer $INSTASENT_TOKEN"
```

```json
{
  "entity": {
    "scope": "channel",
    "projectType": "standard",
    "channel": "sms",
    "percent": 50,
    "operational": true,
    "steps": [
      { "key": "add-sender", "completed": true, "isBlocker": true, "disabled": false, "skipped": false, "skippable": true },
      { "key": "send-first-sms-campaign", "completed": false, "isBlocker": false, "disabled": false, "skipped": false, "skippable": true }
    ],
    "warnings": [
      {
        "key": "recommended-registrations",
        "severity": "error",
        "count": 2,
        "rows": [
          { "channel": "sms", "senderId": "5f3a9b2c4d1e0f00112233ab", "senderName": "MYBRAND", "country": "ES", "source": "regulation", "urgency": "urgent", "audienceCount": null },
          { "channel": "sms", "senderId": "5f3a9b2c4d1e0f00112233ab", "senderName": "MYBRAND", "country": "FR", "source": "audience", "urgency": null, "audienceCount": 412 }
        ]
      }
    ],
    "reach": {
      "reachableCountries": ["PT"],
      "senders": { "MYBRAND": ["PT"] },
      "senderCount": 1,
      "defaultSender": "MYBRAND"
    },
    "computedAt": "2026-09-04T16:20:31Z"
  }
}
```

## Steps

Same [step object](/developers/product-api/project-setup/readiness#a-step) as the project report — stable `key`, no copy — with a set that depends on the channel and the project type:

| `projectType` | `channel` | Steps, in order                                            |
| ------------- | --------- | ---------------------------------------------------------- |
| `standard`    | `sms`     | `add-sender`, `send-first-sms-campaign`                    |
| `standard`    | `rcs`     | `add-agent`, `register-country`, `send-first-rcs-campaign` |
| `api_sms`     | `sms`     | `add-sender`, `send-sms-recent`                            |
| `api_sms`     | `rcs`     | `add-agent`, `register-countries`, `send-rcs-recent`       |

The first step of each list is the blocker; the rest are `disabled` until it is done. `register-country` / `register-countries` completes as soon as one RCS registration has been submitted — submitted, not approved, because approval is the carrier's and the regulator's timeline, not a step the customer can complete. The `*-recent` steps look at the last 30 days, so they re-open on a quiet integration.

**SMS has no per-country step.** Registration exists on SMS too, but it is not something the customer starts by hand, so it never becomes a checklist item. What it does produce is the warning below.

## Warnings

Steps are what the customer can complete. **A warning is what the customer should act on but cannot tick off** — a country a sender ought to be registered for and is not. It appears only once the channel has an active sender: before that there is nothing to recommend registering.

One key:

| `key`                       | `severity` | What it means                                                                                                                 |
| --------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `recommended-registrations` | `error`    | Countries a sender **should** be registered for and is not. `count` is the total and may exceed `rows`, which is capped at 8. |

`warnings` stays an array discriminated by `key` even with a single member, so narrowing on the key is still the right thing to write: the next warning to arrive inherits that shape instead of adding nullable fields to this one.

Every warning carries `key`, `severity`, `count` and `rows`. **`rows` is discriminated by the parent's `key`, never by which fields came back null.**

Rows of `recommended-registrations` describe a registration that does **not** exist, so they carry no status. Instead they say why the country is recommended:

- `channel` — `string`
  `sms` or `rcs`.
- `senderId` — `string`
  The sender the recommendation is for.
- `senderName` — `string`
  Its alias — the SMS `from`, or the RCS agent name.
- `country` — `string`
  ISO 3166-1 alpha-2.
- `source` — `string`
  `regulation` — a regulator requires it; `audience` — you hold contacts there; `org` — it is the organization's own country.
- `urgency` — `string | null`
  `urgent`, `upcoming` or `far`. How close the regulator's deadline is; `null` unless `source` is `regulation`.
- `audienceCount` — `integer | null`
  Reachable contacts in that country; `null` unless `source` is `audience`.

A country already covered by a non-archived registration on that sender never appears here, whatever its status.

> **Note**: `audience` rows are omitted while the audience's country distribution has not been computed yet — it is cached, and warmed when the panel opens a channel page. `regulation` and `org` rows are always there when they apply, so an empty audience contribution is silence, not an error.

### What moved to the attention endpoint

Until 2026-09-05 this array carried two more keys, and if you integrated before that date they are what you are missing:

| Old warning key         | Where it lives now                                                                              |
| ----------------------- | ----------------------------------------------------------------------------------------------- |
| `pending-review`        | [`GET /project/{project}/attention`](/developers/product-api/project-setup/attention), same key |
| `rejected-registration` | [`GET /project/{project}/attention`](/developers/product-api/project-setup/attention), same key |

The key names survived the move, so the switch you already wrote still matches; what changed is the endpoint it reads from and the shape around it — an attention item is **one occurrence** with `entities` and `data`, not a warning with `rows`.

The reason is the boundary the two engines are built on: **readiness answers what is left to configure, attention answers what has broken.** A registration a carrier is still reviewing, or one a regulator turned down, is something that happened to a registration the customer already submitted — an event, not a configuration gap. `recommended-registrations` stayed because it is the opposite: a registration that does not exist yet.

> **Warning**: One consequence worth designing for: a rejected registration appears in **both** reports at once, on purpose. Attention reports the rejection as news, with its cause, for 30 days; readiness lists the country under `recommended-registrations` because a rejected registration is not coverage. They are not duplicates — they say different things and both are true. Render them where each belongs rather than de-duplicating them.

## Reach

`reach` is the positive counterpart of the warnings: **the countries this channel can send to right now.**

- `reachableCountries` — `string[]`
  The union across the channel's active senders, ISO 3166-1 alpha-2, deduplicated and sorted.
- `senders` — `object`
  Per-sender breakdown, keyed by alias. A sender that reaches no country is omitted, so this map can be shorter than the sender list — and it may arrive as `[]` rather than `{}` when it is empty. Normalise both to an empty map before you index it.
- `senderCount` — `integer`
  How many **active** senders the channel has, including those that reach nothing. This is not the size of `senders`, and the gap is the interesting part: an RCS agent with no accepted registration counts here and is absent there.
- `defaultSender` — `string | null`
  The project's default sender, when it is one of the active ones. It matters because a send that names no sender uses it — so the union above can promise more than a single send would actually reach. Always `null` on `api_sms` projects, where nothing picks a default.

Reach is registration-aware: a country drops out when a registration is required and missing, still pending, gated by an enforced regulation, or rejected or revoked. The two channels start from opposite defaults, which is why the same project can look very different on each:

- **SMS** allows by default over the operator catalogue — the same set as the sender's `acceptedCountries` — and subtracts what regulation blocks.
- **RCS** is registration-driven, so it can be **stricter** than the agent's `acceptedCountries`, which reflects carrier support only.

## `operational` on a channel

On this scope `operational` asks for more than the project one does: **no incomplete blocker step *and* at least one reachable country.**

That second clause is not redundant. Holding a sender is not the same as being able to deliver with it: an RCS agent with no accepted registration completes `add-agent` and still reaches nobody. `operational` claims capability, so it answers to reach.

> **Tip**: Before a send, `operational` plus `reach.reachableCountries` is the whole pre-flight: the first says the channel works, the second says where. If you also need to know whether there is anyone there, [count the audience](/developers/product-api/audience/counting-and-retrieval#counting).

---

This is one page of the Instasent documentation. For the complete machine-readable index of every guide and API reference, fetch https://docs.instasent.com/llms.txt — start there for full context.
