Single and batch sending
Send single or batch messages and handle whole-batch validation, per-message results, idempotency, and retries.
Use single send for one message and batch send for multiple messages. Both return HTTP 202 with code=000000 on acceptance.
Endpoints and uses
| Method | Path | Successful acceptance |
|---|---|---|
| Single | POST /innomail/v2/messages/send | HTTP 202 + code=000000 |
| Batch | POST /innomail/v2/messages/batchsend | HTTP 202 + code=000000; returns batch and message IDs |
Marketing and transactional email
| Type | Typical use | Recipient rules |
|---|---|---|
MARKETING | Promotions, campaigns, newsletters | The original object must contain exactly one To and empty or omitted Cc/Bcc. |
TRANSACTIONAL | Verification codes, orders, bills, service notices | Multiple To/Cc/Bcc are allowed: at most 50 entries per field and 100 unique recipients in total. |
A non-template request without messageType defaults to MARKETING; a template can determine the type. Do not label promotional content as transactional to bypass marketing recipient rules.
Body and template content
- Direct body: provide non-empty
textorhtml, or both. Plain text and HTML become different content parts; providing both is recommended for marketing compatibility. - Template: provide
template.templateIdwithout non-emptytext/html.subjectremains required and can contain variables. variablesonly render templates; they do not replace placeholders in directly suppliedtext/html.- There is no usable attachment upload or content-store capability. An attachment reference in the request model does not mean an attachment will be delivered; omit
attachments.
See Templates and variables for creation, review, and rendering rules.
Single-message lifecycle
- The platform authenticates the request, validates it, and checks idempotency.
- Save the returned
messageIdand readX-Request-Idfrom the response headers. - Later delivery stages check sender authorization, templates, message type, suppression, and channel routing.
- Use send records or Webhooks for the final result;
ACCEPTEDdoes not mean delivered.
Batch behavior before and after acceptance
Before acceptance: validate the whole batch
messages must contain 1–100 items, each with the same structure as a single message. If any item fails field or business validation, the entire batch is rejected and no item is accepted. Rate limits count message items rather than HTTP requests; insufficient capacity also rejects the whole batch.
After acceptance: process each message independently
Once accepted, each message independently undergoes template, sender identity, suppression, and channel checks. A batch can therefore contain delivered, bounced, rejected, and failed messages at the same time.
{
"messages": [
{
"from": {"email": "news@example.com"},
"to": [{"email": "alice@example.net"}],
"subject": "Product update",
"html": "<p>Hello Alice</p>",
"messageType": "MARKETING"
},
{
"from": {"email": "news@example.com"},
"to": [{"email": "bob@example.net"}],
"subject": "Product update",
"html": "<p>Hello Bob</p>",
"messageType": "MARKETING"
}
]
}This submits two independent marketing messages and does not expose Alice's address to Bob. acceptedCount counts accepted objects, not delivered recipients. messages[].index maps to the input array index, and messages[].messageId identifies each message.
Invalid recipient addresses
Addresses within an object are deduplicated case-insensitively in To, Cc, then Bcc order. If a transactional message has some malformed addresses but at least one valid recipient, invalidRecipients can contain a precheck summary. If all addresses are invalid, the request is rejected before acceptance.
This summary is not a final failure list. Mailbox existence, bounces, complaints, and suppression require later delivery results. Marketing messages must satisfy the single-recipient rule in the original request; deduplication cannot be used to bypass it.
Idempotency and retries
- Give each independent business task a unique
X-Idempotency-Keyof at most 128 characters, and persist it with the request body before the first call. - Under the same AppID and endpoint, the same key and content replay the original result; an in-progress task returns a conflict; different content returns a content conflict.
- Single and batch endpoints have separate idempotency namespaces. Batch retries must preserve the entire array content and order.
- Results are retained for 24 hours by default, subject to the actual environment. An expired key is not long-term duplicate protection.
- With CheckSum, generate a new Nonce, CurTime, and CheckSum for every HTTP attempt while preserving the original key and body.
| Situation | Recommended action |
|---|---|
HTTP 202 with code=000000 | Accepted. Save IDs and do not resubmit the same task. |
| Parameter, authentication, or permission error | Correct the request and re-sign; first ensure the original request was not accepted. |
| Idempotency in progress | Retry the original key and body with limited backoff; contact the platform if it persists. |
| Idempotency content conflict | Stop automatic retries and check whether another task reused the key. |
| Short-term rate limit | Reduce rate or batch size; honor Retry-After. |
| Daily quota reached | Wait for the UTC day boundary or contact the platform. |
| 5xx, timeout, or disconnected connection | The outcome can be unknown. Retry only with the original key and body; never blindly resend with a new key. |
If batch publication is interrupted, some items may already be accepted. An error response does not prove zero items were sent. Do not wait for the idempotency record to expire and then resend blindly. Ask the platform to reconcile using the AppID, idempotency key, traceId/requestId, and any batchId/messageId already obtained; never provide the API Secret.
FAQ
Does acceptance mean delivery?
No. Acceptance only starts processing. Use send records or Webhooks for the final outcome.
Related resources
Last updated on