sayintel
Endpoint

Get draft qa

GET/api/public/v1/campaigns/{campaign_id}/qaread

Machine-readable QA state for drafts. Pass speaker_id alone to inspect one speaker, or campaign_id for the whole campaign. Returns per-message qa_score, qa_evaluated_at, qa_flags, hard-fail codes, actionable fix hints ({code, action, hint}) — covering both scored hard-fail codes AND qa_flags-only signals like m2/m3_no_rotation or a founder approval/rejection stamp, which never appear in qa_reasons but can still make needs_human true on an otherwise clean score-8 draft — needs_human / needs_redo, approvable flag, plus per-speaker buckets (ready_to_send | needs_rewrite | needs_human | awaiting_qa | skipped | sent) and a rollup of the most common fail codes. A fix with action 'none' means don't touch this slot (already approved/locked); 'rescore' means the text was hand-edited and has no score yet, so run rescore_drafts (a clean score releases it); 'human_review' means a person must decide, not an automated rewrite (clear it with approve_message once they have). Use this to decide what to rewrite (request_rewrite) before pushing. Filter with only_failing=true. Paginated: pass next_cursor while has_more is true.

Request

curl "https://sayintel.com/api/public/v1/campaigns/<campaign_id>/qa" \
  -H "Authorization: Bearer $SAYINTEL_TOKEN"

Try it out

Try it outGET/api/public/v1/campaigns/{campaign_id}/qaread

Sent as a bearer token to this site only, and kept in this tab's session storage. It is never written to disk or sent anywhere else.

Paste an API key to run.

Path parameters

NameInTypeRequiredDescription
campaign_idpathstringyesRequired unless speaker_id is given.

Query parameters

NameInTypeRequiredDescription
speaker_idquerystringno—
only_failingquerybooleannoOnly return unsent drafts that are not approvable (hard fail, low score, or unevaluated). The filter runs in the query, so has_more is exact: paging to has_more=false is guaranteed to have shown you every failing draft.
limitquerynumberno—
cursorquerystringnoOpaque cursor from a previous call's next_cursor. Omit for the first page.

Response

{
  "ok": true,
  "tool": "get_draft_qa",
  "kind": "read",
  "data": { ... },
  "error": null
}

Notes

  • Scope required: read. How scopes work.
  • Paginated. Pass the returned next_cursor while has_more is true.
  • Same capability over MCP as the tool get_draft_qa. MCP setup.