All pages

Start a batch

One call, one domain, up to 100 briefs. Rows are accepted or refused individually rather than the whole call failing, so a batch that runs past a limit still starts everything there was room for.

POST/v1/editions/{slug}/articles/batch

Parameters

ParamInNotes
slugpathThe domain UUID. Every row in a batch is written for this one domain.
jobsbodyRequired. 1 to 100 rows, each shaped exactly like the single-article body. Two rows may not share an id.

Request

curl -X POST https://api.mastheads.app/v1/editions/3f9c1e84-2b7a-4d6e-9c15-8a0d7e6b4f21/articles/batch \
  -H "Authorization: Bearer mh_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"jobs": [{"input": "Harbour timetable"}, {"input": "Bus lane consultation"}]}'

Response

202 Accepted
{
  "accepted": [
    "7c2b9f10-4a5d-4e88-9b31-6f0c2a1d5e73",
    "b8e0f3a6-91c4-4d20-8f7e-33ac1b5d9e04"
  ],
  "refused": [
    {
      "index": 2,
      "job_id": null,
      "detail": "not started - this key's hourly limit of 20 API actions leaves room for 2"
    }
  ],
  "ids": [
    "7c2b9f10-4a5d-4e88-9b31-6f0c2a1d5e73",
    "b8e0f3a6-91c4-4d20-8f7e-33ac1b5d9e04"
  ]
}

The call is 202 even when some rows are refused: nothing is silently dropped, so read refused rather than only checking the status code. A batch is cut at whichever limit bites first - this key's hourly room, the newsroom's own ceiling, or the plan's allowance.

FieldTypeNotes
acceptedarrayThe job ids that were started. Poll each on GET /v1/jobs/{id}.
refusedarrayOne object per row that did not start, each with its input index, its job_id when you sent one, and a detail sentence saying why.
idsarrayEvery row that was handed on, in the order you sent them. It is how a caller who sent no ids of their own matches a refusal back to a row.

Errors

StatusCodeWhen
401invalid_keyMissing, invalid, or revoked API key.
401account_closedThe account this key belongs to has been closed.
402plan_requiredThe account's current plan does not include the content API. This is checked on the request, not only when the key was made.
503unavailableThe plan or the data store could not be read. It refuses rather than guessing.
402payment_requiredA guard behind the door refused on plan or billing grounds. The message says which.
403key_read_onlyThe key was created as Read only. A key's permission is fixed when it is made, so create a new key with Full access.
403wrong_newsroomA full-access key spends only in the newsroom its owner was in when it was created. If that person now acts in a different newsroom, create a new key there. A read-only key is not gated this way.
403forbiddenA guard behind the door refused. The message says which.
404not_foundNo such domain on your account, or the path segment is not a UUID. Another tenant's domain is a 404, never a 403.
422invalid_paramsThe body did not validate: a missing or over-long input, an id that is not a UUID, more than 100 rows, or two rows sharing an id.
429rate_limitedOver this key's 20 paid actions an hour, or over its 120 requests/minute. Retry-After: 60, and nothing was started.

Every request needs a key - Authentication. The error shape and the full status table are on Rate limits & errors.