Search the docs
Find a page, a section, or an endpoint.
Attachments
Every attachments endpoint, generated from the API's own schemas.
Upload a file to send
post/api/v1/attachments
Multipart, with `identity_id` and `file` parts — not base64 in JSON, because a ten-megabyte PDF is thirteen megabytes of base64 and every proxy in between would have to be told. **Under 4 MB only**: the platform refuses a request body over 4.5 MB with its own `413`, whatever your plan allows, so use `POST /attachments/uploads` for anything larger. Name the returned id in `attachment_ids` on a send. An upload expires in a day: it is a file no message refers to yet.
Parameters
- Idempotency-Keystring
Any string unique to this attempt, reused on its retries. A repeat with the same key and the same request returns the first answer with `Idempotent-Replay: true` and does nothing — no second email. The same key with a different request is a `409`. Kept for 24 hours; a failure is not kept, so a retry after one runs.
Responses
- 201The upload.
- 400The request is not valid. `error.field` names the input at fault when there is one.
- 401No API key, or one that is not valid.
- 403Refused. `error.code` says why: `forbidden` when this key may not do this or the account is on hold, `abuse_blocked` when a limit says no.
- 404No such resource, or one this key cannot reach. The two answer the same, so treat a 404 as “not available to you” rather than “does not exist”.
- 409Nothing was done by this call. `error.code` says which: `idempotency_in_progress` when the first request with this `Idempotency-Key` has not answered yet (wait `Retry-After` seconds and send it again), `idempotency_mismatch` when the key was used with a different request (use a new key).
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
- 500Something went wrong on our side. Retry; if it keeps happening, tell us.
- 503Something this needs is not answering right now. Retry in a moment.
- 504Test mode only: `Pidgeon-Test-Fail: drop` dropped the answer (`test_dropped`). The request was done; retry it with the same `Idempotency-Key` to get the first answer.
curl https://pidgeon.ai/api/v1/attachments \
-X POST \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ … }'Get a download link for an attachment
get/api/v1/attachments/{id}
A signed URL rather than the bytes: streaming a 25 MB file through the API costs the transfer twice and gains the caller nothing. The link expires.
Parameters
- idstring
Responses
- 200The link.
- 400The request is not valid. `error.field` names the input at fault when there is one.
- 401No API key, or one that is not valid.
- 403Refused. `error.code` says why: `forbidden` when this key may not do this or the account is on hold, `abuse_blocked` when a limit says no.
- 404No such resource, or one this key cannot reach. The two answer the same, so treat a 404 as “not available to you” rather than “does not exist”.
- 409It conflicts with what is there: it already exists, or the `etag` you sent is not the current one.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
- 500Something went wrong on our side. Retry; if it keeps happening, tell us.
- 503Something this needs is not answering right now. Retry in a moment.
curl https://pidgeon.ai/api/v1/attachments/{id} \
-H "Authorization: Bearer $PIDGEON_API_KEY"Upload a large file straight to storage
post/api/v1/attachments/uploads
For a file of any size up to your plan’s limit. Say what it is — `identity_id`, `filename`, `content_type` and `size` in bytes — and the answer’s `upload` is a signed URL: `PUT` the bytes there with the `headers` it lists, within 15 minutes. The size and type are signed, so a body of another length or type is refused. Then call `POST /attachments/{id}/complete`; until then a send naming the id is a `409`. The same checks as `POST /attachments`: `draft` on the address, the allowed types, the plan’s per-file size. Expires in a day if never sent.
Parameters
- Idempotency-Keystring
Any string unique to this attempt, reused on its retries. A repeat with the same key and the same request returns the first answer with `Idempotent-Replay: true` and does nothing — no second email. The same key with a different request is a `409`. Kept for 24 hours; a failure is not kept, so a retry after one runs.
Body
- identity_iduuid
The address this belongs to.
- filenamestring
- content_typestring
- sizenumber
Responses
- 201The upload to make.
- 400The request is not valid. `error.field` names the input at fault when there is one.
- 401No API key, or one that is not valid.
- 403Refused. `error.code` says why: `forbidden` when this key may not do this or the account is on hold, `abuse_blocked` when a limit says no.
- 404No such resource, or one this key cannot reach. The two answer the same, so treat a 404 as “not available to you” rather than “does not exist”.
- 409Nothing was done by this call. `error.code` says which: `idempotency_in_progress` when the first request with this `Idempotency-Key` has not answered yet (wait `Retry-After` seconds and send it again), `idempotency_mismatch` when the key was used with a different request (use a new key).
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
- 500Something went wrong on our side. Retry; if it keeps happening, tell us.
- 503Something this needs is not answering right now. Retry in a moment.
- 504Test mode only: `Pidgeon-Test-Fail: drop` dropped the answer (`test_dropped`). The request was done; retry it with the same `Idempotency-Key` to get the first answer.
curl https://pidgeon.ai/api/v1/attachments/uploads \
-X POST \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ … }'Read an attachment as text
get/api/v1/attachments/{id}/text
A CSV, a log, JSON or another text format (up to 5 MB), or a PDF, a `.docx` or an `.xlsx` (up to 10 MB), as text: the first 200,000 characters of it. Screened by Pidgeon Firewall with the sender of the message it came with, because a file in an email is mail a model reads: `firewall` says whether it tries to steer you, and `body=clean` returns it with hidden content removed. Text a document hides from a person (a hidden Word run, a hidden sheet, row or column) counts as hidden text. Where the address holds suspicious mail, a flagged attachment holds its message, and a key is answered `403 held`. A scanned or password-protected PDF, `.doc`, `.xls`, PowerPoint, HTML and images are refused; `GET /attachments/{id}` gives a link to those.
Parameters
- idstring
- bodyenum
original · clean
Responses
- 200The text.
- 400The request is not valid. `error.field` names the input at fault when there is one.
- 401No API key, or one that is not valid.
- 403Refused. `error.code` says why: `forbidden` when this key may not do this or the account is on hold, `abuse_blocked` when a limit says no.
- 404No such resource, or one this key cannot reach. The two answer the same, so treat a 404 as “not available to you” rather than “does not exist”.
- 409It conflicts with what is there: it already exists, or the `etag` you sent is not the current one.
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
- 500Something went wrong on our side. Retry; if it keeps happening, tell us.
- 503Something this needs is not answering right now. Retry in a moment.
curl https://pidgeon.ai/api/v1/attachments/{id}/text \
-H "Authorization: Bearer $PIDGEON_API_KEY"Finish a large upload
post/api/v1/attachments/{id}/complete
After the `PUT` to the URL `POST /attachments/uploads` gave you. Checks that the file arrived at the size and type declared and makes the id sendable. A `409` means nothing has arrived yet. Safe to repeat.
Parameters
- idstring
- Idempotency-Keystring
Any string unique to this attempt, reused on its retries. A repeat with the same key and the same request returns the first answer with `Idempotent-Replay: true` and does nothing — no second email. The same key with a different request is a `409`. Kept for 24 hours; a failure is not kept, so a retry after one runs.
Responses
- 200The upload, ready to send.
- 400The request is not valid. `error.field` names the input at fault when there is one.
- 401No API key, or one that is not valid.
- 403Refused. `error.code` says why: `forbidden` when this key may not do this or the account is on hold, `abuse_blocked` when a limit says no.
- 404No such resource, or one this key cannot reach. The two answer the same, so treat a 404 as “not available to you” rather than “does not exist”.
- 409Nothing was done by this call. `error.code` says which: `idempotency_in_progress` when the first request with this `Idempotency-Key` has not answered yet (wait `Retry-After` seconds and send it again), `idempotency_mismatch` when the key was used with a different request (use a new key).
- 429Rate limited. `X-RateLimit-Reset` says when to retry.
- 500Something went wrong on our side. Retry; if it keeps happening, tell us.
- 503Something this needs is not answering right now. Retry in a moment.
- 504Test mode only: `Pidgeon-Test-Fail: drop` dropped the answer (`test_dropped`). The request was done; retry it with the same `Idempotency-Key` to get the first answer.
curl https://pidgeon.ai/api/v1/attachments/{id}/complete \
-X POST \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ … }'