API reference · Native API (v1)
Send up to 100 emails atomically
POST
https://api.pidgely.com/v1/emails/batchSends 1 to 100 emails atomically (all or nothing).
Authorization: Bearer pdg_…. Any API key (full or sending scope).
Body parameters
A JSON array of objects (1–100 items). Each item:
| Name | Type | Required | Description |
|---|---|---|---|
from |
string | No | Name <addr@verified-domain>; may come from the template. |
to |
string | string[] | Yes | Recipient address (a@x.com or Name <a@x.com>) or a list of them. Up to 50 unique recipients across to, cc and bcc. |
cc |
string | string[] | No | Carbon-copy recipients. Count toward the 50-recipient limit. |
bcc |
string | string[] | No | Blind carbon-copy recipients. Count toward the 50-recipient limit. |
reply_to |
string | string[] | No | Reply-To address or list of addresses. |
subject |
string | No | Subject line, up to 998 bytes. Required unless a template provides it. |
html |
string | No | HTML body. html or text is required (unless you send with a template). |
text |
string | No | Generated from html when omitted. |
headers |
object (map of string) | No | Custom headers. Platform-managed headers (From, To, Subject, Message-ID, DKIM-Signature, Return-Path, Reply-To, …) are rejected; values cannot contain line breaks. |
attachments |
object[] | No | Files to attach. All attachments share a 40 MiB budget (decoded). Executable types (.exe, .js, .bat, …) are blocked. |
attachments[].filename |
string | No | File name shown to the recipient. Defaults to the last segment of path. |
attachments[].content |
string | No | Base64 content. Use either content or path. |
attachments[].path |
string | No | http(s) URL downloaded at send time (SSRF-guarded, 40MB budget, no redirects). |
attachments[].content_type |
string | No | MIME type. Guessed from the file extension when omitted. |
attachments[].content_id |
string | No | Makes the attachment inline (cid: in HTML). |
tags |
object[] | No | Name/value pairs attached to the email and returned in webhooks. |
tags[].name |
string | Yes | Display name. Pattern: ^[A-Za-z0-9_-]{1,256}$. |
tags[].value |
string | Yes | Pattern: ^[A-Za-z0-9_-]{1,256}$. |
scheduled_at |
string | No | ISO 8601 or natural language (in 1 hour, tomorrow at 9am); within 30 days. |
template |
object | No | — |
template.id |
string | Yes | Template id or alias (published version is used). |
template.variables |
object (map of string | number) | No | Values for the template variables: strings up to 2,000 characters or numbers. |
topic_id |
string | No | Not supported yet; a non-empty value is rejected. |
stream |
string | No | Pidgely extension: transactional (default) or broadcast (adds RFC 8058 unsubscribe). One of transactional, broadcast. |
Request
curl -X POST 'https://api.pidgely.com/v1/emails/batch' \
-H "Authorization: Bearer $PIDGELY_API_KEY" \
-H 'Content-Type: application/json' \
-d '[
{
"from": "Acme <onboarding@acme.com>",
"to": [
"delivered@example.com"
],
"subject": "Welcome to Acme",
"html": "<p>Thanks for signing up!</p>",
"tags": [
{
"name": "category",
"value": "welcome"
}
]
}
]'Response
200 OK with a JSON object.
Errors
Native routes return {"error": {"code", "message", "field", "request_id"}}. See Errors.
| Status | Code | When |
|---|---|---|
| 401 | missing_api_key |
No Authorization: Bearer header. |
| 403 | invalid_api_key, insufficient_scope |
The key is invalid or lacks the scope. |
| 404 | not_found |
The resource does not exist in this account. |
| 422 | validation_error |
A field is missing or invalid; field names it. |
| 429 | rate_limited, daily_quota_exceeded |
Too many requests, or the quota is used up. |