Use case · Orders, shipping, invoices

An order confirmation email API with your order ID on every event.

tinyRelay sends order confirmations, receipts, shipping notifications and invoice emails from your backend over a REST API or SMTP relay. Attach an order_id to each recipient and it comes back on every signed webhook event for that email.

Webhook events · order_id: SO-1001
  • DELIVEREDReceiving server accepted itorder_id ✓
  • CLICKurl: https://acme.com/orders/SO-1001order_id ✓
One request · two recipients · two order IDs
  • DELIVEREDann@example.com · order_id: SO-1merged ✓
  • DELIVEREDbob@example.com · order_id: SO-2merged ✓
Webhook events · invoice_id + order_id
  • CLICKurl: https://acme.com/invoices/INV-20412 keys ✓
  • BOUNCEDSOFT_BOUNCED · category 22 · retry laterif it fails

Example emails and metadata · illustrative

Why metadata

"Where is my receipt?" should take one lookup.

Every webhook event carries the metadata you sent. Store events against the order ID and support can see, for any order, whether the confirmation was sent, delivered, opened, clicked or bounced.

10keys
Keys per email

Metadata keys per email, counted after request-level and recipient maps merge.

e.g. order_idmerged
500recipients
Recipients with own metadata

Per request, so one batch can carry a different order_id for each recipient.

One batchown order_id each
7event types
Event types

Each event type carries your metadata back to your webhook.

SEND → SPAMechoed
412
Over a limit

Returned if a request breaks the limits, before anything sends.

Resultnothing sent

Limits from the tinyRelay Send Email docs.

The order lifecycle

Order confirmation, shipping notification, invoice email.

Pick a stage to see the email, the request that sends it and the events that come back.

Events for ann@example.com · metadata { order_id: SO-1001 }
  • SENDSent to the receiving serverorder_id ✓
  • DELIVEREDReceiving server accepted itorder_id ✓
  • CLICKurl: https://acme.com/orders/SO-1001order_id ✓

Order confirmation: one order, one request

Send the confirmation as soon as the order is placed. A campaignId unique to the order keeps its metadata separate from every other send.

POST /email/campaign · bodyCopy
{
  "subject": "Order SO-1001 is confirmed",
  "body": "<html>Hi [FIRST_NAME], thanks for your order…</html>",
  "sender": { "from": { "name": "Acme Store", "email": "orders@acme.com" } },
  "recipients": { "to": [
    { "email": "ann@example.com", "attributes": { "FIRST_NAME": "Ann" } }
  ] },
  "campaignId": "order_confirmed_SO-1001",
  "metadata": { "order_id": "SO-1001", "tenant_id": "acme" }
}
One request · two recipients · two order IDs
  • DELIVEREDann@example.com · order_id: SO-1merged ✓
  • DELIVEREDbob@example.com · order_id: SO-2merged ✓
  • OPENann@example.com · tenant_id: acme · app: checkoutmerged ✓

Shipping notification email: a batch, per-recipient IDs

When a batch of orders ships, send one request. Shared metadata goes at the top; each recipient's own order_id goes on the recipient. The maps merge and the recipient's keys win, so Ann's events carry tenant_id, app and SO-1.

POST /email/campaign · body (from the docs example)Copy
{
  "subject": "Your order shipped",
  "body": "<html>Hi [FIRST_NAME]</html>",
  "sender": { "from": { "name": "Shop", "email": "orders@shop.com" } },
  "campaignId": "order_shipped_batch_17",
  "metadata": { "tenant_id": "acme", "app": "checkout" },
  "recipients": { "to": [
    { "email": "ann@example.com",
      "attributes": { "FIRST_NAME": "Ann" },
      "metadata": { "order_id": "SO-1" } },
    { "email": "bob@example.com",
      "attributes": { "FIRST_NAME": "Bob" },
      "metadata": { "order_id": "SO-2" } }
  ] }
}

The docs example uses "order_shipped"; a unique campaignId per batch keeps each batch's metadata intact.

Events · metadata { invoice_id: INV-2041, order_id: SO-1001 }
  • DELIVEREDReceiving server accepted it2 keys ✓
  • CLICKurl: https://acme.com/invoices/INV-20412 keys ✓
  • BOUNCEDSOFT_BOUNCED · category 22 · retry laterif it fails

Invoice email: link to the hosted invoice

Send the invoice notice with both IDs as metadata, so a CLICK on "View invoice" ties back to the invoice and the order. Attachments are not covered in the current API docs, so this example links to a hosted invoice.

POST /email/campaign · bodyCopy
{
  "subject": "Your invoice INV-2041",
  "body": "<html>Hi [FIRST_NAME], <a href=\"https://acme.com/invoices/INV-2041\">view invoice</a></html>",
  "sender": {
    "from": { "name": "Acme Store", "email": "billing@acme.com" },
    "replyTo": { "name": "Acme Billing", "email": "help@acme.com" }
  },
  "recipients": { "to": [
    { "email": "ann@example.com", "attributes": { "FIRST_NAME": "Ann" } }
  ] },
  "campaignId": "invoice_INV-2041",
  "metadata": { "invoice_id": "INV-2041", "order_id": "SO-1001" }
}

Every field above is in the Send Email reference. Requests go to POST https://api.tinyemail.com/v1/relay/email/campaign with your key in X-RELAY-ACCESS-TOKEN.

Base URL from current site samples; confirm in the docs.

Receipt email API rules

Metadata rules worth knowing before launch.

They are small, and each one prevents a confusing support case later.

How the email API works →
  1. 1
    10 keys in total, not per level
    Request-level and recipient metadata merge into one map of at most 10 keys. Keys up to 64 characters, values up to 256.
  2. 2
    Flat values only
    Strings, numbers or booleans. Numbers and booleans come back as strings. Nested objects, arrays and null are not supported.
  3. 3
    Keys are normalised
    Keys become lowercase snake_case: OrderID comes back as order_id. Two keys that normalise to the same name are rejected.
  4. 4
    Attributes are not metadata
    Attributes fill merge tags such as [FIRST_NAME] and are never echoed. Metadata never appears in the email and is always echoed.
  5. 5
    One campaignId per batch
    Reusing a campaignId replaces the earlier metadata, including per-recipient entries. Use a unique one, or omit it and the requestId is used.
SMTP from store platforms

Already sending from a store platform? Use SMTP.

If your store platform or framework lets you set an external SMTP server, point it at the tinyRelay SMTP relay with the credentials issued at onboarding. No code changes to your templates.

The per-recipient metadata shown above is documented for the REST API. Ask our team how SMTP sends map to webhook events for your setup.

SMTP settings

Entered once in your platform's email settings.

Host[SMTP host]
Port[port]
Username and passwordIssued at onboarding
Sender domainDKIM via one CNAME

Host, port and TLS settings to be confirmed before launch.

FAQ

Order email questions.

Sending security or billing alerts too? See account notifications.

Can one request send shipping emails for many orders?

Yes. One request can carry many recipients, each with their own attributes and their own metadata, such as a different order_id. At most 500 recipients in one request may carry their own metadata.

Up to 10 keys in total after request-level and recipient metadata are merged. Keys can be up to 64 characters and values up to 256 characters. A request that breaks the limits is rejected with 412 before any email is sent.

If your store platform or framework lets you set an external SMTP server, you can point it at tinyRelay with the SMTP credentials issued at onboarding. The metadata fields on this page are documented for the REST API.

Attachments are not covered in the current tinyRelay API docs. The invoice example on this page links to a hosted invoice instead. Ask our team if you need attachments.

Metadata is scoped to the campaignId. If two requests share one, the later request's metadata replaces the earlier one, including every per-recipient entry. A unique campaignId per batch, or none at all, keeps them apart.

Get started

Send transactional email with a service that reports back.

SMTP relay or REST API, standalone or alongside tinyEmail. Tell us what you send and our team sets you up.