waiaconnect

Documentation / Complete

Sending status: can this number start conversations?

GET /v1/connections/{id}/sending-status

Markdown

Building with AI? Connect it to your account over MCP: it checks your setup, creates webhooks and templates with your confirmation and writes the code for you. See how →

Before a campaign, GET /v1/connections/{id}/sending-status ({id} = conn_… or your externalId) tells you whether to pause before piling up rejections and what your customer has to fix. It comes from what we already read from Meta: it does not call Meta.

canSend: available, limited, blocked or unknown (not read yet), with canSendReason. Replying inside a customer's 24 h window does not depend on it.

Why. entities[] (WhatsApp Business Account, portfolio, app and number, each with its verdict and Meta's codes) and reasonCodes[] with the original code: 141006 payment method, 141010 business verification, 131042 while Meta keeps rejecting sends for the payment. Also businessVerification, accountReviewStatus, qualityRating, payment (ok, missing or unknown; never card data) and links to the Meta page that fixes it.

Daily limit. messagingLimit.tier and dailyLimit: Meta applies it to the portfolio, shared by all its numbers and providers. Meta does not expose the consumption in the moving 24 h window or the next release: they come as unknown, never estimated. Same for payment.fundingSource and payment.creditLine.

Re-read. When your customer says it is fixed: POST /v1/connections/{id}/sending-status/refresh re-reads from Meta (read-only), once per number every 10 min; before that, 429 RATE_LIMITED with Retry-After.

Notices. Subscribe your webhook to connection.sending_status_changed (by name) and get every change with changed, the previous signature and the full state.

# 1) before a campaign: can this number start conversations?
curl https://api.waiaconnect.com/v1/connections/conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sending-status -H "Authorization: Bearer wc_live_YOUR_API_KEY"
# → { "sendingStatus": { "canSend": "blocked", "reasonCodes": [141006],
#       "payment": { "status": "missing", "owner": "client", … },
#       "messagingLimit": { "tier": "TIER_250", "dailyLimit": 250, "used": "unknown", … }, … } }

# 2) your customer says they fixed it: re-read from Meta (once per number every 10 min)
curl -X POST https://api.waiaconnect.com/v1/connections/conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sending-status/refresh -H "Authorization: Bearer wc_live_YOUR_API_KEY"
const H = { "Authorization": "Bearer wc_live_YOUR_API_KEY" };
const { sendingStatus: s } = await (await fetch("https://api.waiaconnect.com/v1/connections/conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sending-status", { headers: H })).json();
if (s.canSend === "blocked" || s.canSend === "limited") {
  // pause the campaign and tell your customer what to fix
  console.log(s.reasonCodes, s.payment.status, s.businessVerification.status, s.links.paymentSettings);
}
<?php
$ch = curl_init("https://api.waiaconnect.com/v1/connections/conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sending-status");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer wc_live_YOUR_API_KEY"]]);
$s = json_decode(curl_exec($ch), true)["sendingStatus"];
if (in_array($s["canSend"], ["blocked", "limited"])) {
  // pause the campaign; $s["reasonCodes"], $s["payment"]["status"], $s["links"]["paymentSettings"]
}
import requests
H = {"Authorization": "Bearer wc_live_YOUR_API_KEY"}
s = requests.get("https://api.waiaconnect.com/v1/connections/conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sending-status", headers=H).json()["sendingStatus"]
if s["canSend"] in ("blocked", "limited"):
    print(s["reasonCodes"], s["payment"]["status"], s["links"]["paymentSettings"])  # pause + guide your customer
# after your customer fixed it (once per number every 10 min):
requests.post("https://api.waiaconnect.com/v1/connections/conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sending-status/refresh", headers=H)

A number of another account gets the same 404 CONNECTION_NOT_FOUND as one that doesn't exist.

readAt says when it was read; it is re-read every 12 h and on the refresh.

message.status carries Meta's original code (errors[], with subcode on a send rejection), the stage (stage: send or delivery) and Meta's pricing (billable, category, type) for reconciliation.