HelipodDocs

Limits and errors

Rate limits, size limits, plan limits, sending reputation and every error code the Email API returns.

Rate limit

Each API key may make 10 requests per second. The allowance is a bucket of 10 that refills continuously, so a short burst is fine and a brief pause restores it.

Every response carries:

HeaderMeaning
x-ratelimit-limitRequests allowed per second (10).
x-ratelimit-remainingRequests left in the bucket right now.
retry-afterOn a 429 only: seconds to wait before retrying.

Over the limit, the API answers 429 with code RATE_LIMITED:

{ "success": false, "error": "Rate limit exceeded: 10 requests per 1s. Retry in 1s.", "code": "RATE_LIMITED" }

A batch of 50 messages is one request, so batching is the way to send faster.

Size and count limits

WhatLimit
Recipients per message (to + cc + bcc, after duplicates are removed)50
Entries in each of to, cc, bcc1 to 50
Messages per batch50
Recipients per batch, all messages together50
html, text per message500,000 characters each
subject500 characters
Address fields (from, replyTo, each recipient)320 characters
idempotencyKey128 characters
Attachmentsnot supported
Template name63 characters (letters, digits, _, -)
Template htmlBody, textBody200,000 characters each
Broadcast body500,000 characters
Contacts per POST /contacts1,000
Custom properties stored per call50 (keys up to 100 characters)
CSV import10,000,000 characters; first 5,000 rows are read
CSV export50,000 contacts
Segment filter rules20
Topic ids per PUT /contacts/{id}/topics50
Webhook url2,000 characters, https:// only
Webhook events20 entries
Inbox bulk update500 ids
Forwarding addresses per mailbox5
Page size (limit)emails, contacts, inbox messages: 1 to 200 (default 50); suppressions: 1 to 500 (default 100); broadcast recipients: 1 to 500 (default 100)

Plan limits

Your plan sets how many emails you can send per day and per month, and how many domains, templates, contacts, segments, topics, webhooks, mailboxes and aliases the project can have, and whether broadcasts and forwarding are included. Read the current values from GET /status (plan) and GET /inbound/stats.

  • Quota is counted per recipient and reserved when a message is accepted. Rejected sends do not count.
  • The daily limit (on plans that have one) resets at 00:00 UTC.
  • The monthly window starts on your subscription date.
  • Past the monthly limit, sending continues only with pay-as-you-go enabled. See Quota and billing.

Hitting a plan limit returns 402 with a specific code (for example DOMAIN_LIMIT_REACHED). Upgrade the plan in the dashboard, or remove something you no longer need.

Reputation

Bounces and spam complaints hurt the reputation that your mail is delivered on. Helipod Email watches each project's rolling rates:

  • Bounce rate above 2% or complaint rate above 0.08% (the exact limits for your project are in GET /analytics under limits) suspends sending for the project: sends return 403 REPUTATION_SUSPENDED. The suspension lifts automatically once the rates are back under the limits, or after the project has been quiet for a while.
  • If the combined reputation of all senders is at risk, sending can be paused for every project: sends return 403 PLATFORM_REPUTATION, and platformPaused in GET /status explains why.

Keep lists clean: send only to people who asked for your mail, remove addresses that bounce, and make unsubscribing easy.

Errors

Every error uses the same envelope:

{ "success": false, "error": "Human readable message", "code": "MACHINE_CODE" }

Branch on code. Messages are meant for people and can change.

HTTP status codes

StatusMeaning
200, 201OK, created.
202Accepted. The work continues in the background (a jobId is returned).
400The request broke a rule. See the code.
401Missing, invalid or expired API key.
402Plan, quota or balance limit.
403Not allowed right now: unverified domain, suppressed recipient, or sending suspended.
404Not found.
409Conflict: already exists, or the resource is in the wrong state.
422The request body or query does not match the schema (VALIDATION).
429Rate limited.
500Unexpected error. Retry with backoff; use idempotencyKey on sends.
503Temporarily unavailable. Retry shortly.

Authentication and request

CodeStatusMeaning
NO_API_KEY401No Authorization: Bearer header, or an empty key, on a send endpoint.
UNAUTHORIZED401No Authorization: Bearer header on any other endpoint.
INVALID_API_KEY401The key does not exist or was revoked.
API_KEY_EXPIRED401The key's expiry date has passed.
NO_PLAN402The project has no active email plan. Reading the status and plan, and buying or renewing a plan, still work.
KEY_NOT_ALLOWED403The route stays in the dashboard: email keys, cancelling the plan, its billing switches, mailbox passwords.
IDEMPOTENCY_KEY_REQUIRED400A plan purchase with a key was sent without an Idempotency-Key header. See Plan and add-ons.
NO_CONFIG404The key's email configuration no longer exists.
EMAIL_NOT_SETUP403The email service is not activated for the project.
PROJECT_NOT_FOUND404The project does not exist.
VALIDATION422A body, query or path field is missing or invalid. The message names the field.
RATE_LIMITED429Too many requests. See retry-after.
NOT_FOUND404No such route.
INTERNAL_ERROR500Unexpected error.

Sending

CodeStatusMeaning
NO_RECIPIENTS400to is empty.
INVALID_RECIPIENT400An address is malformed or uses a reserved domain. The message lists each one with the reason.
RECIPIENT_DOMAIN_UNDELIVERABLE400A recipient's domain does not exist or cannot receive mail.
TOO_MANY_RECIPIENTS400More than 50 recipients in a message or in a batch.
EMPTY_BODY400None of html, text or templateId.
SUBJECT_REQUIRED400No subject on a send without a template.
INVALID_HEADER400A line break in subject, from or replyTo, or an invalid custom header.
INVALID_FROM400from is not a valid address.
ATTACHMENTS_NOT_SUPPORTED400attachments was sent.
INVALID_COMBINATION400templateId combined with custom headers.
MISSING_VARIABLES400A {{token}} has no value in variables or templateData.
VARIABLES_REQUIRED400The content has {{tokens}} but no variables were sent.
NO_MESSAGES400A batch with no messages.
TOO_MANY_MESSAGES400A batch with more than 50 messages.
BATCH_FAILED400Every message of a batch failed; per-message results are in data.
TEMPLATE_NOT_FOUND404templateId is not a template of this project.
DOMAIN_NOT_FOUND403The from domain is not added to the project.
DOMAIN_NOT_VERIFIED403The from domain is not verified yet.
RECIPIENT_SUPPRESSED403A recipient is suppressed, or previously bounced or complained.
REPUTATION_SUSPENDED403Sending is suspended for the project because of its bounce or complaint rate.
PLATFORM_REPUTATION403Sending is paused for every project.
TENANT_PAUSED403Sending is paused for the project by the delivery network. Contact support.
SENDING_DISABLED403Sending is turned off for the project.
DAILY_QUOTA_EXCEEDED402The daily limit is reached.
MONTHLY_QUOTA_EXCEEDED402The monthly limit is reached and the plan has no pay-as-you-go rate.
PAYG_DISABLED402The monthly limit is reached and pay-as-you-go is off.
INSUFFICIENT_BALANCE402Pay-as-you-go needs more wallet deposit.
WALLET_NOT_FOUND404No wallet for pay-as-you-go.
PLAN_NOT_FOUND404The active plan could not be loaded.

In a batch, a rejected message can also carry code: "UNKNOWN" for an unexpected per-message error.

Domains

CodeStatusMeaning
INVALID_DOMAIN400Not a valid domain name.
DOMAIN_EXISTS409Already added to this project.
DOMAIN_LIMIT_REACHED402The plan allows no more domains.
DOMAIN_NOT_FOUND404No such domain.

Templates

CodeStatusMeaning
INVALID_TEMPLATE_NAME400Name has characters other than letters, digits, _ and -, or is too long.
EMPTY_TEMPLATE400Neither htmlBody nor textBody.
TEMPLATE_LIMIT_REACHED402The plan allows no more templates.
TEMPLATE_NOT_FOUND404No such template.

Contacts, segments and topics

CodeStatusMeaning
CONSENT_REQUIRED400A bulk add or import without consentConfirmed: true.
INVALID_EMAIL400A contact address is not valid.
DISPOSABLE_EMAIL400A contact uses a disposable inbox provider.
RECIPIENT_DOMAIN_UNDELIVERABLE400A contact's domain cannot receive mail.
EMPTY_REQUEST400No contacts in the request.
TOO_MANY400More than 1,000 contacts in one request.
EMPTY_CSV400The CSV has no header or no data rows.
CSV_MISSING_EMAIL400The CSV header has no email column.
NO_VALID_CONTACTS400Every CSV row was rejected.
INVALID_CURSOR400cursor is not a value returned by the previous page.
RECIPIENT_SUPPRESSED403A contact address is on the suppression list.
CONTACT_LIMIT_REACHED402The plan's contact limit would be exceeded.
SEGMENT_LIMIT_REACHED402The plan allows no more segments.
TOPIC_LIMIT_REACHED402The plan allows no more topics.
CONTACT_NOT_FOUND404No such contact.
SEGMENT_NOT_FOUND404No such segment.
TOPIC_NOT_FOUND404No such topic, or an unknown id in topicIds.

Broadcasts

CodeStatusMeaning
INVALID_SCHEDULE400scheduledAt is not a future date.
NO_RECIPIENTS400Nobody in the audience can be sent to. The message lists a few skipped recipients and why.
BROADCASTS_NOT_ALLOWED402The plan does not include broadcasts.
BROADCAST_NOT_FOUND404No such broadcast.
BROADCAST_LOCKED409The broadcast's status does not allow this action, or a send is already starting.
BROADCAST_SENDING409Cannot delete while sending. Cancel first.
SEND_UNAVAILABLE503Sending cannot start right now. Retry shortly.

Sending a broadcast can also return the sending, domain, quota and reputation codes above.

Logs, suppressions and jobs

CodeStatusMeaning
EMAIL_NOT_FOUND404No such email.
SUPPRESSION_NOT_FOUND404No such suppression entry.
JOB_NOT_FOUND404No such job.
INVALID_CURSOR400cursor is not a value returned by the previous page.

Webhooks

CodeStatusMeaning
INVALID_URL400Not an https:// URL with a public, fully qualified hostname, or it contains credentials.
NO_EVENTS400No valid event name in events.
WEBHOOK_LIMIT_REACHED402The plan allows no more webhooks.
WEBHOOK_NOT_FOUND404No such webhook.

Inbox

CodeStatusMeaning
PLAN_REQUIRED402The plan does not include receiving.
INVALID_HOST400The receiving host is not the domain or one of its subdomains, or it is the MAIL FROM host.
DOMAIN_NOT_VERIFIED409Verify the domain before enabling receiving.
INBOUND_HOST_TAKEN409The host already receives mail in another project.
DOMAIN_NOT_RECEIVING409Enable receiving on the domain before creating addresses.
INVALID_ADDRESS400Invalid local part or forwarding address.
ADDRESS_EXISTS409The address already exists.
ADDRESS_NOT_FOUND404No such address.
MAILBOX_NOT_FOUND404The mailbox for an alias was not found.
MAILBOX_LIMIT402The plan allows no more mailboxes.
ALIAS_LIMIT402The mailbox has the maximum number of aliases.
FORWARDING_NOT_ALLOWED402The plan does not include forwarding.
ALIAS_SETTINGS400Mailbox-only settings (name, forwarding, notifications, password) were set on an alias.
WEAK_PASSWORD400The webmail password is shorter than 10 characters.
MESSAGE_NOT_FOUND404No such message.
ATTACHMENT_NOT_FOUND404No attachment with that index.
RAW_NOT_AVAILABLE404The original message was not kept.
INVALID_FOLDER400Unknown folder, or a draft moved anywhere but trash.
NOTHING_TO_UPDATE400None of isRead, isStarred, folder.
TOO_MANY_IDS400More than 500 ids in a bulk update.
BODY_REQUIRED400A reply with neither text nor html.
INVALID_CURSOR400cursor is not a value returned by the previous page.

On this page