Search the docs

Find a page, a section, or an endpoint.

Drafts

A message not sent yet, and sending it later.

A draft is a message that has not been sent. An agent that writes a reply, waits for a person to approve it, and sends it an hour later is ordinary supervised automation — and this is where the hour in the middle lives.

curl https://pidgeon.ai/api/v1/drafts \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "identity_id": "idn_4f2a1",
  "to": "priya@example.com",
  "subject": "Re: Invoice 4471",
  "text": "Reissued, thank you."
}'

Only identity_id is required. A draft with nothing else in it is a legitimate thing to create — it is what a composer does when somebody opens it — and the rest arrives by PATCH as they type.

Changing one

PATCH keeps what you leave out, so saving as somebody types is a body with the field that changed:

sh
PATCH /v1/drafts/dft_91ca   { "text": "Reissued yesterday, thank you." }

Sending it

sh
POST /v1/drafts/dft_91ca/send

What is stored is what goes. There is no body, because a draft that needed arguments at the moment of sending would be a message you had not finished writing.

Sending answers with the message, and the draft is gone — it became the thing it was for.

Sending it later

curl https://pidgeon.ai/api/v1/drafts/dft_91ca/schedule \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "send_at": "2026-11-04T09:00:00Z" }'

A minute from now at the earliest and thirty days at the latest. DELETE on the same path takes the schedule off and leaves an ordinary draft.

A refused send unschedules rather than retrying. If the address cannot write to that recipient when the time comes — a send policy, a suppression — the draft comes back to you with the reason, instead of a job trying again every hour until somebody notices.

Attaching a file

Upload it first, then name it on the draft. Attachments has the upload; attachment_ids is where it goes, and DELETE /v1/drafts/{id}/attachments/{attachmentId} takes one off again.