Mailings

The Mailings app plans and sends marketing mails, from the draft and its checklist to the schedule, the send, and the statistics, click map and revenue of each mailing.

This page is the API reference for developers reading or writing marketing mailings.

The Mailings app holds one planned send of one marketing mail to one audience under one subscription type. A new mailing is a draft. It can be scheduled only when its checklist has no error (warnings do not block), and then the send pipeline reads the audience in pages, asks the Marketing consents app who may receive it, drops recipients held back as graymail, and hands the batches to the messaging service. The Audiences app supplies the audience. The app keeps the figures of each mailing (recipient outcomes, opens, clicks, unsubscribes, complaints and revenue) and answers them for the mailing and the sending health of the last 30 days.

Known limit: the messaging service does not yet accept the recipient batches a mailing hands over, so a scheduled mailing reaches nobody for now. What happens next depends on the error. A network error, a 429 or a 5xx from the messaging service is treated as temporary: the mailing stays sending, the send run retries, and after 12 failed runs it ends failed. Any other error status fails the mailing on the first run, with a failure_reason such as sequencer_refused:404. A mailing scheduled to send at once shows the same failure in the run field of its schedule response. Test sends and previews work, and they are the way to check a mailing until this is lifted.

Objects

ObjectWhat it holds
MailingThe name, subject, preview_text, sender, sender_name, reply_to, audience_id, exclude_audience_ids, subscription_type, template_key, voucher_batch_id, send_at, timezone_mode, graymail and graymail_sends, campaign_ref, the state and the list folder, and the counters such as recipients_count, sent_count and revenue, and the figures open_rate_percent, click_rate_percent and unsubscribed_count (read-only, see below), and the six trash fields.
RecipientOne row per audience member of a mailing, with its outcome (queued, sent, ineligible, graymail, suppressed, invalid or excluded).
StatsThe figures of one mailing: deliveries, bounces, opens, clicks and revenue.
ClickOne clicked link of a mailing, with its clicks and unique clickers.
EngagementOne announcement from the messaging service that the app recorded for a mailing. Read only.
VariantAn A/B variant of a mailing. Reserved for a later version; the list is always empty in this one.

A mailing has one state: draft, scheduled, sending, sent, cancelled or failed. The folder is the list view it sits in: drafts, scheduled, sent or archived. A mailing that is in the trash is left out of every view until it is restored.

Base path: https://api.revenexx.com/v1/mailings.

Scopes

A key calls these routes with the capability key of each route. The App's manifest names one per operation, in the form mailings.<group>.<operation>, and the API keys page explains that a key holds capability keys or a namespace such as mailings.*. The scope names are listed in the tables below. A call that needs a scope the key does not hold is refused with 403.

Mailings

OperationScopeWhat it does
GET /v1/mailings/mailingsmailings.mailings.listLists the mailings of the tenant. The trash is left out unless trashed asks for it.
POST /v1/mailings/mailingsmailings.mailings.createWrites a mailing down as a draft.
GET /v1/mailings/mailings/{id}mailings.mailings.getReads one mailing.
PUT /v1/mailings/mailings/{id}mailings.mailings.updateChanges a mailing.
DELETE /v1/mailings/mailings/{id}mailings.mailings.deleteMoves a mailing into the trash. A second DELETE on the same mailing deletes it for good, and a storefront contact is refused that second call with 403.
POST /v1/mailings/mailings/trash/emptymailings.mailings.empty-trashDeletes every mailing in the trash for good.
POST /v1/mailings/mailings/trash/purgemailings.mailings.purgeDeletes the mailings that have been in the trash longer than the tenant's trash retention. It is the nightly purge, callable by hand.
  • List filters: folder (drafts, scheduled, sent or archived), state, campaign_ref, audience_id, subscription_type, template_key, starter, timezone_mode, duplicated_from_id, id, and trashed (exclude, only or include). limit takes 1 to 200 (default 50), with offset and order (a column, optionally .asc or .desc).
  • Create body: required name. Every other field is optional. sender and sender_name come from the market settings named in the X-Revenexx-Market header, or from the tenant settings. starter is blank (default), simple, newsletter or promotion. timezone_mode is tenant (default: everybody gets send_at at the same moment) or recipient (send_at is read as wall-clock time in each recipient market time zone). graymail is on by default, and graymail_sends takes 1 to 100. subject and preview_text are stored as given: the checklist fails a subject over 150 characters and warns on a preview text over 200. exclude_audience_ids takes at most 10 ids. Create answers 400 for a sender or reply_to that is not an email address, ids that are not UUIDs, a currency that is not three letters, and an audience that is both sent to and excluded.
  • Figures on a mailing: read-only, mirrored from its statistics. A value sent for them on a create or update is dropped.
    • open_rate_percent (number): unique human opens divided by deliveries, 0 to 100.
    • click_rate_percent (number): unique clicks divided by deliveries, 0 to 100.
    • unsubscribed_count (integer): recipients who unsubscribed through this mailing.
  • Update: a draft changes freely, and so does a cancelled or failed mailing that nobody received (sent_count is 0). In any other state only name, campaign_ref and metadata change. A content change is refused with 409 and mailing_locked, with details.fields naming the fields.
  • Delete: only a mailing that nobody received (sent_count is 0) can go into the trash. Any other mailing is refused with 409 and trash_blocked, its blocker naming mailing_sent: cancel a scheduled or sending mailing first, and archive one that reached recipients. A mailing in the trash counts nowhere until it is restored.
  • Empty trash and purge: a call from a storefront contact is 403 with purge_not_allowed. One empty-trash call handles at most 1000 trashed rows. A mailing that something still blocks stays in the trash, and the answer names it with its reason. The purge deletes nothing when the retention cannot be read.
  • Errors on the mailing routes: 404 when no mailing has the id. 409 with in_trash when a mailing in the trash is changed, duplicated, archived, scheduled, cancelled or test-sent: restore it first. Reads, the checklist, reach, preview and the figures still answer for it. Restoring a mailing that is not in the trash is 409 with not_in_trash.

Lifecycle

OperationScopeWhat it does
POST /v1/mailings/mailings/{id}/restoremailings.mailings.restoreTakes a mailing back out of the trash, in the state it was in.
POST /v1/mailings/mailings/{id}/duplicatemailings.mailings.duplicateCopies a mailing into a new draft. Any mailing outside the trash can be copied, sent ones included. The copy keeps the content, audience and settings, drops the send time and the campaign, and is named <name> (Kopie).
POST /v1/mailings/mailings/{id}/archivemailings.mailings.archiveMoves a mailing to the archive.
POST /v1/mailings/mailings/{id}/unarchivemailings.mailings.unarchiveTakes a mailing out of the archive.
GET /v1/mailings/mailings/{id}/checklistmailings.mailings.checklistReads what must be true before the mailing may be scheduled.
GET /v1/mailings/mailings/{id}/reachmailings.mailings.reachReads how many people the mailing would reach.
POST /v1/mailings/mailings/{id}/schedulemailings.mailings.scheduleRuns the checklist and schedules the mailing.
POST /v1/mailings/mailings/{id}/cancelmailings.mailings.cancelCancels a scheduled or sending mailing.
POST /v1/mailings/mailings/{id}/previewmailings.mailings.previewRenders the mailing as one recipient sees it. Nothing is sent. A voucher block shows a fixed sample voucher code instead of drawing a real one from the batch.
POST /v1/mailings/mailings/{id}/testmailings.mailings.testSends the mailing to colleagues as a test.
  • Archive: a scheduled or sending mailing is refused with 409 and mailing_active. Cancel it first. A sent mailing can be archived, and it comes back with unarchive.
  • Checklist: each item has ok, a severity (error or warning), a state (ok, warning or error), a label, the problem as a sentence, and where to put it right. Only errors block a schedule. ready is true when no error stands, and the answer lists the failing items by errors and warnings. The text follows Accept-Language, and German is the default unless English is asked for. The items are subject, preview_text, sender, audience, subscription_type, template, footer_address, unsubscribe, links, alt_texts, voucher_batch and send_time.
    • Errors: a missing subject (or one over 150 characters), sender, audience, subscription type, template, postal address or unsubscribe link; a link that leads nowhere; a send time in the past; a voucher block without a voucher batch, or a batch that is gone or cannot be read; and any check the other app could not answer.
    • Warnings: a missing or over-long (over 200 characters) preview text, a missing alt text, an audience with no members right now, and a voucher batch named for a template that has no voucher block.
  • Reach: the audience member and eligible counts, the excluded audiences, and held_back_at_most, an upper bound on how many addresses graymail protection would hold back. It counts engagement rows across the whole tenant that are at or over the threshold, not only the rows of this audience.
  • Schedule body: send_at (an ISO time, or now, null or "" to send at once; left out, the mailing's own send_at holds), start (false leaves even a send-at-once mailing to the next pipeline run) and timezone_mode (tenant or recipient).
  • Schedule errors: 409 with checklist_failed and the items when an error stands. 409 with not_schedulable when the mailing is scheduled, sending or sent, or a cancelled or failed mailing that reached recipients (sent_count above 0). 409 with in_trash when it is in the trash. 400 when send_at is not a time or timezone_mode is not tenant or recipient.
  • Cancel: nothing more is handed to the messaging service. Recipients already handed over keep their mail. 409 with not_cancellable when the mailing is not scheduled or sending, and state_changed when it changed while the call ran.
  • Preview body: market (the market to price and render for), locale, device (desktop or mobile, a label only), contact_id, email (a placeholder address by default), first_name and last_name. Products are priced for the market named, and the footer is that market's. Nothing is sent. Errors: 409 with template_missing when there is no template or its key is unknown, 502 with sequencer_unavailable when the template list cannot be read, and 502 with preview_failed when rendering fails.
  • Test body: recipients, at most 10 addresses, as a list or as a string separated by commas, semicolons or spaces. Without it the test recipients from the app settings are used. market and locale are optional. Each address is sent on its own: one that fails does not fail the call, and the answer lists each address with sent true or false, plus the number sent. An address that was sent carries a message_id and no reason; an address that failed carries a reason. The template receives a [Test] subject prefix in its data. When the mailing names a voucher batch, a fixed sample voucher code is used; no code is drawn from the batch. The test counts in no figure. Errors: 400 with no code when there are more than 10 recipients, 400 with no_test_recipients or invalid_address (details.invalid lists the addresses), 409 with template_missing or in_trash, and 502 with sequencer_unavailable.

Statistics and analysis

OperationScopeWhat it does
GET /v1/mailings/mailings/{id}/statsmailings.analysis.statsReads what one mailing achieved.
GET /v1/mailings/mailings/{id}/clicksmailings.analysis.clicksReads the click map of one mailing.
GET /v1/mailings/mailings/{id}/timelinemailings.analysis.timelineReads the opens and clicks of one mailing per day.
GET /v1/mailings/statsmailings.analysis.list-statsLists the figures of mailings.
GET /v1/mailings/stats/{id}mailings.analysis.get-statsReads one figures row.
POST /v1/mailings/stats/sweepmailings.analysis.sweepBrings the figures of the last 30 days up to date. It is the hourly job, callable by hand.
GET /v1/mailings/clicksmailings.analysis.list-clicksLists the clicked links of mailings.
GET /v1/mailings/clicks/{id}mailings.analysis.get-clickReads one clicked link.
GET /v1/mailings/engagementsmailings.analysis.list-engagementsLists the announcements recorded for mailings. Read only.
GET /v1/mailings/engagements/{id}mailings.analysis.get-engagementReads one recorded announcement.
  • Stats: the recipient outcomes, deliveries, bounces, opens by people and by machines apart, clicks, click rate, click-to-open, unsubscribes, complaints and revenue. The open and click rates use unique clicks and human opens; the bounce, unsubscribe and complaint rates use their own counts. Machine opens are the opens a mail client or a bot makes by itself, for example when it prefetches the pixel.
  • Click map: every clicked link with its clicks, unique clickers and share of all clicks, the most clicked first.
  • Timeline: human opens and clicks per day in the tenant time zone, at most the latest 60 days. Machine opens are left out.
  • Sweep: recomputes revenue from the campaigns ledger and raises the delivered and clicked figures to what the messaging service reports.

Recipients

OperationScopeWhat it does
GET /v1/mailings/recipientsmailings.recipients.listLists the recipients of mailings.
GET /v1/mailings/recipients/{id}mailings.recipients.getReads one recipient row.
  • List filters: mailing_id for one mailing, outcome for one outcome, and id, contact_id, email, reason, market and message_id. Paging is limit, offset and order, as on the mailings list.
  • Recipient rows are written by the send pipeline only. A caller cannot change them.

Sending and health

OperationScopeWhat it does
POST /v1/mailings/send/runmailings.send.runRuns the send pipeline once. It prepares due and unfinished mailings chunk by chunk until the time budget is spent.
GET /v1/mailings/healthmailings.health.readReads the sending health of the last 30 days.
  • Send run: the five-minute schedule, callable by hand. Until the known limit above is lifted, a run cannot hand batches to the messaging service.
  • Health: sent, delivered, bounced, complained and unsubscribed counts over the mailings of the last 30 days, with their rates. alert is set when the complaint rate passes the threshold in the app settings.

Variants, blocks and vocabularies

OperationScopeWhat it does
GET /v1/mailings/variantsmailings.variants.listLists the A/B variants of mailings. Empty in this version.
GET /v1/mailings/variants/{id}mailings.variants.getReads one variant.
GET /v1/mailings/blocksmailings.blocks.readReads the product, voucher and footer blocks: the keys each carries in a design and the variables that fill it per recipient.
GET /v1/mailings/vocabulariesmailings.vocabularies.listLists the closed vocabularies the app enforces.
GET /v1/mailings/vocabularies/{name}mailings.vocabularies.getReads one vocabulary with its values and labels. 404 when there is no such vocabulary.
Was this page helpful?