Search the docs
Find a page, a section, or an endpoint.
Drafts
Every drafts endpoint, generated from the API's own schemas.
Every draft in one mailbox
get/api/v1/drafts
Newest first, and including scheduled ones — a scheduled message is a draft with `send_at` set. `GET /mailboxes/drafts` lists the same rows as a mail client draws them: sender, subject, preview. This gives the recipients and the body, because a caller here is coming back to finish writing.
Parameters
- identity_iduuid
- limitnumber
Responses
- 200The drafts.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts \
-H "Authorization: Bearer $PIDGEON_API_KEY"Write one without sending it
post/api/v1/drafts
An agent that drafts a reply, waits for a human to approve it and sends it an hour later is ordinary supervised automation, and this is where the half-written message lives in the meantime. Idempotent with `Idempotency-Key`.
Body
- identity_iduuid
- fromstring
- toemail[]
- ccemail[]
- bccemail[]
- subjectstring | null
- textstring | null
- in_reply_to_message_iduuid | null
- attachment_idsuuid[]
Responses
- 201The draft.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts \
-X POST \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ … }'Fetch one draft
get/api/v1/drafts/{id}
Parameters
- idstring
Responses
- 200The draft.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts/{id} \
-H "Authorization: Bearer $PIDGEON_API_KEY"Change some of it, and leave the rest
patch/api/v1/drafts/{id}
An omitted field survives; `null` clears it. Both are needed, because "I am not touching the subject" and "there is no subject" are different instructions.
Parameters
- idstring
Body
- fromstring
- toemail[]
- ccemail[]
- bccemail[]
- subjectstring | null
- textstring | null
- attachment_idsuuid[]
Responses
- 200The draft.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts/{id} \
-X PATCH \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ … }'Throw it away
delete/api/v1/drafts/{id}
Parameters
- idstring
Responses
- 200Deleted.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts/{id} \
-X DELETE \
-H "Authorization: Bearer $PIDGEON_API_KEY"Send what is stored
post/api/v1/drafts/{id}/send
No body: the row is the message. The browser passes the composer contents and the draft id together, because the composer *is* the draft; a caller here saved it an hour ago and may be a different process. `PATCH` first to change anything. The id that comes back is the draft's, because a send converts the row.
Parameters
- idstring
Responses
- 202Accepted.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts/{id}/send \
-X POST \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ … }'Send it later
post/api/v1/drafts/{id}/schedule
A minute from now at the earliest, thirty days at the latest. A refused send unschedules rather than retrying forever, so a draft can come back on its own with `failed_reason` set — read that before scheduling the same message again.
Parameters
- idstring
Body
- send_atdate-time
Responses
- 200The draft.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts/{id}/schedule \
-X POST \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ … }'Back to being an ordinary draft
delete/api/v1/drafts/{id}/schedule
Parameters
- idstring
Responses
- 200The draft.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts/{id}/schedule \
-X DELETE \
-H "Authorization: Bearer $PIDGEON_API_KEY"Take a file off a draft
delete/api/v1/drafts/{id}/attachments/{attachmentId}
The object goes with the row. An attachment belongs to its draft rather than being shared, so leaving the bytes behind would be storage nobody can reach and everybody is billed for. `POST /attachments` is how one gets on.
Parameters
- idstring
- attachmentIdstring
Responses
- 200Deleted.
- 401No API key, or one that is not valid.
- 404No such resource, **or** one belonging to another account. The two are deliberately indistinguishable: a different answer would enumerate what exists.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
curl https://pidgeon.ai/api/v1/drafts/{id}/attachments/{attachmentId} \
-X DELETE \
-H "Authorization: Bearer $PIDGEON_API_KEY"