Skip to main content

Errors

Public API errors use application/problem+json and the RFC 9457 Problem shape:

{
"type": "urn:phishinghermes:problem:unsupported_media_type",
"title": "Unsupported media type",
"status": 415,
"detail": "Content-Type must be message/rfc822.",
"instance": "urn:phishinghermes:request:req_synthetic_0001",
"code": "unsupported_media_type",
"request_id": "req_synthetic_0001"
}

Every public response carries Cache-Control: no-store and X-Request-ID. The body request_id matches the header. A Problem can include errors only for safe field-level validation details.

The read-only API Reference contains a complete, schema-valid, sanitized RFC 9457 example for every public code listed below.

Complete catalog

StatusPublic codes and common causesRetry?Idempotency keyRecommended action
400invalid_request, invalid_content_length, idempotency_key_required, invalid_idempotency_key: malformed framing, length, or operation keyNoKeep it while diagnosingCorrect the request before sending it again
401invalid_credentials: missing or non-authenticating credential; deliberately genericNoUnchangedCorrect or rotate the credential; do not probe credential states
403insufficient_capability, credential_environment_mismatch, credential_not_customer_bound, service_not_enabled, entitlement_required: authenticated scope is not authorizedNoUnchangedUse the credential issued for this customer/environment or contact Hermes
404operation_not_found: unknown public path, including a non-canonical trailing-slash pathNoUnchangedUse exactly /v1/email-analyses
405method_not_allowed: a method other than POST was usedNoUnchangedUse POST; the response also sends Allow: POST
408request_body_timeout: the complete body did not arrive before the body-read deadlineYes, boundedSame key and bytesCheck upload/network behavior, then retry with backoff
409idempotency_conflict: the same key was already used with different bytesNoRecover original bytes; otherwise new key only for a genuinely new operationNever bypass the conflict automatically
413payload_too_large: body exceeds 10 MiBNoUnchangedDo not truncate evidence silently; use an approved alternative workflow
415unsupported_media_type, unsupported_content_encoding: body is not raw message/rfc822 or is compressedNoUnchangedCorrect headers and send the original bytes
422unusable_email, email_too_complex: empty/NUL/headerless/bodyless or over structural limitsNoUnchangedRe-export the source or use an approved alternative workflow
429rate_limit_exceeded, usage_quota_exceeded, usage_quota_temporarily_reserved, analysis_concurrency_limitedYes, boundedSame key and bytesHonor Retry-After when present, add jitter, reduce concurrency
500internal_error: unexpected failure before a safe public resultYes, boundedSame key and bytesBack off; do not assume retry will resolve it
503Temporary authentication/rate/processing/persistence/accounting unavailability, timeout, still-processing idempotency, or uncertain outcomeYes, boundedSame key and bytesHonor Retry-After when present; never create a new key to bypass uncertainty

Public 503 codes are:

authentication_unavailable
rate_limit_unavailable
service_deadline_exceeded
email_parsing_unavailable
email_parsing_timeout
idempotency_unavailable
idempotency_in_progress
analysis_outcome_unknown
analysis_timeout
analysis_unavailable
idempotency_ownership_lost
analysis_persistence_unavailable
analysis_tenant_binding_failed
usage_accounting_unavailable

idempotency_in_progress and analysis_outcome_unknown require special care: retry the original operation with the same key and byte buffer. Do not generate another key. Hermes sends Retry-After where the specific path can calculate a useful interval; the header is not guaranteed for every 429 or 503.

The facade does not return 402.

Safe error handling

content_type = response.headers.get("content-type", "")
if response.status_code >= 400:
if "application/problem+json" not in content_type:
response.raise_for_status()
problem = response.json()
raise RuntimeError(
f"Hermes {problem['status']}: {problem['code']} "
f"(request_id={problem['request_id']})"
)

Log only stable status, code, request ID, and approximate UTC time. Never log the API key, EML, attachments, or sensitive headers.

When to contact support

Stop bounded retries and contact info@phishinghermes.com when a retryable failure persists, an uncertain outcome remains unresolved, or a permanent response is unclear. Provide the latest request_id, status, code, UTC time, client/library version, and whether every retry used the same key and bytes.