422unprocessable
Refused by current state
The request is well formed, and the current state of what it addresses refuses it. The message says what is in the way.
Every value in the request is legal, and the thing it acts on is not in a state that allows it: an article that has already been sent, a newsletter with no verified sending address, a slug another article already uses. Changing the request's syntax will not help. Changing the state will, or choosing a different target.
Most of these come from the article lifecycle (POST /articles/{article}/send, /schedule, /unschedule, /test-send, and PATCH /articles/{article}) and from tags. param is set when one field is responsible (slug, name, tag, attempt). The message always says what state is in the way, and nothing was changed.
A newsletter that is published through another provider has its own code, not_commune_newsletter.
Why it happens, and how to fix it
The newsletter cannot send yet
Sending, scheduling and test sends need a sending address. The newsletter has none, or its address is not verified yet (the message gives the verification state).
Fix: Add or verify the sending address on the newsletter's Domains page in the Commune dashboard.GET /newsletters/{newsletter}/sendersandGET /senders/{sender}report each address's state and the DNS records that complete verification.The article cannot be sent as it is
The send and schedule gates refused the article's body. It is empty. Or it is missing the unsubscribe link, the mailing address (
{{ address }}), or both, which commercial email must carry; Commune seeds them into every draft and this gate cannot be bypassed. Or an image in it could not be loaded, which would break it for every recipient (an image host that is only slow is never reported).Fix: Put content in the body (content_markdownonPATCH /articles/{article}). Restore the unsubscribe link and mailing address that were edited out of the footer. For images, re-upload or remove the ones the message lists, or send again with{"acknowledge_broken_images": true}in the body if you accept them broken.The article is in the wrong state
Only a draft, a scheduled article or one whose last send failed can be sent or scheduled; one that is sending, sent or archived cannot.
POST /articles/{article}/unscheduleneeds an article that is scheduled.PATCH /articles/{article}refuses an article that is sending (wait for it to finish), sent (an email cannot be recalled), archived (unarchive it in Commune first), or imported from the newsletter's provider (it can never be edited here).Fix: Read the article withGET /articles/{article}and checkstatusandis_imported, then act on what it says. To send the same content again, create a new article.The state changed during the request, or the time has passed
The article moved between the check and the change, usually because another request sent or scheduled it at the same moment. On
POST /articles/{article}/schedule, ascheduled_forin the past is refused the same way rather than sent immediately.Fix: Read the article again and decide from its currentstatus. For scheduling, send ascheduled_forin the future, in UTC or with an explicit offset.A slug or tag name is already taken
Article slugs are unique within a newsletter, and tag names are unique among a newsletter's live tags.
paramisslugorname.Fix: Choose another value. For an article, you can leaveslugout and Commune derives a free one from the title.The tag is retired
A tag that was deleted after an article was sent to it is kept as retired, because it still decides who may read that article. A retired tag cannot be renamed or added to anyone new (
paramisnameortag). Removing it from a subscriber still works.Fix: Create a new tag withPOST /newsletters/{newsletter}/tagsand use that instead.GET /tags/{tag}shows whether a tag is retired.Other refusals with a clear target
POST /threads/{thread}/publishwas given the id of a reply rather than a thread.POST /delivery-attempts/{attempt}/replaywas asked to redeliver to a destination that is switched off (paramisattempt). A test send was refused by the sending service for a reason the message quotes.Fix: Publish the thread the reply belongs to (its id is thethreadon the message). Enable the destination in the delivery portal, whichPOST /newsletters/{newsletter}/portal-sessionopens, then replay. For a test send, act on the reason in the message.
Retrying
No: the same request is refused until the state it names changes, so fix that state (or pick another target) and then send it again, with the same Idempotency-Key if you like, since nothing was changed.
Example response
{
"error": {
"code": "unprocessable",
"message": "This newsletter's sending address is not verified, so no email can go out from it. Its verification is `pending`. The DNS records that finish verification are on the sender, which the `senders` operations return.",
"request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
"docs_url": "https://usecommune.dev/errors/unprocessable"
}
}Often confused with not_commune_newsletter, bad_request, conflict.