sayintel
Endpoint

Approve message

POST/api/public/v1/campaigns/{campaign_id}/approvalswrite

Record a PERSON's decision that drafts are fine as written: clears needs_human and needs_redo, removes review-hold flags (e.g. copilot_rewritten_awaiting_review, *_awaiting_review, agent_authored_*, founder_rejected_*) and stamps founder_approved_text_<date>. Only call it when the user has read the text and said to approve it. Target message_ids or speaker_ids (all their unsent slots). Refuses, per row, anything never evaluated or carrying a hard fail. It never invents a score: qa_score is left as is, so a row approved with no score or below 8 is approved but still not ready_to_send, and the response says so (run rescore_drafts first). Does not send or push by itself, but on a campaign with HeyReach auto-push armed clearing the hold is part of sending, so there it requires the 'send' token scope and is refused otherwise.

Request

curl -X POST "https://sayintel.com/api/public/v1/campaigns/<campaign_id>/approvals" \
  -H "Authorization: Bearer $SAYINTEL_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'

Try it out

Try it outPOST/api/public/v1/campaigns/{campaign_id}/approvalswrite

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_idpathstringyes—

Body

NameInTypeRequiredDescription
message_idsbodyarrayno—
speaker_idsbodyarraynoApprove every unsent slot of these speakers.

Response

{
  "ok": true,
  "tool": "approve_message",
  "kind": "write",
  "data": { ... },
  "error": null
}

Notes

  • Scope required: write. How scopes work.
  • Accepts Idempotency-Key. A retry with the same key replays the first result instead of repeating the work.
  • Same capability over MCP as the tool approve_message. MCP setup.