Submit an email
Use POST /v1/email-analyses with the complete email as the binary request body.
Required headers
| Header | Contract |
|---|---|
X-API-Key | Credential issued by Hermes; never place it in a URL |
Idempotency-Key | 8–128 safe ASCII characters for one logical submission |
Content-Type | message/rfc822; media-type parameters are accepted |
X-Request-ID is optional. Supply 8–80 safe, non-secret characters matching ^[A-Za-z0-9][A-Za-z0-9._:-]{7,79}$. Hermes replaces an invalid value with a generated identifier and echoes the accepted identifier in the response header and body.
Omit Content-Encoding or send identity. Compressed bodies are rejected.
Preserve the original bytes
Read the .eml as bytes once and reuse that same byte buffer for retries. Include original headers, MIME boundaries, bodies, and attachments. Do not:
- convert the message to JSON;
- send multipart form data;
- extract only visible text;
- base64-encode the whole request;
- silently truncate headers or remove attachments.
IDEMPOTENCY_KEY="submit-$(uuidgen)"
curl --request POST \
"$HERMES_API_BASE_URL/v1/email-analyses" \
--header "X-API-Key: $HERMES_API_KEY" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--header "Content-Type: message/rfc822" \
--data-binary @message.eml
Processing limits
| Limit | Maximum |
|---|---|
| Complete EML body | 10,485,760 bytes (10 MiB) |
| Header block | 262,144 bytes (256 KiB) |
| Header count across the parsed message | 500 |
| One logical header | 65,536 bytes (64 KiB) |
| MIME parts | 200 |
| MIME nesting depth | 20 |
| Attachments | 50 |
| Aggregate decoded part data | 10,485,760 bytes (10 MiB) |
Exceeding the complete-body limit returns 413 payload_too_large. Structurally excessive messages return 422 email_too_complex.
Minimum usable message
Hermes rejects an empty body, NUL bytes, or input without an analyzable RFC 5322 header/body section. A message must contain recognizable email headers and a body. Some imperfect but tolerably parseable MIME is accepted with malformed_message_accepted; invalid UTF-8 replacement is reported as invalid_utf8_replaced.
Synchronous completion
The server's current wall-clock processing budget defaults to 45 seconds and cannot be configured above 120 seconds. This is a processing bound, not a latency or availability SLA. Set a per-attempt client timeout above the server ceiling and also enforce a finite overall retry deadline.
If a client timeout or network interruption leaves the outcome unknown, retry with the same idempotency key and exactly the same bytes. Do not create a new key merely because no response arrived.