Guide

Custom Preference URLs

Point unsubscribe and preference-center links to your own domain while ArtaMail continues to sign tokens and process consent.

By default, links resolve to ArtaMail: https://artamail.artatol.net/api/u/{token}. In Settings → Subscription consent you can set a custom URL template such as:

text
https://prefs.acme.com/manage?token={{token}}

At send time ArtaMail replaces {{token}} with a signed HMAC token. The same built URL is used in email body links and in List-Unsubscribe headers (Gmail one-click).

Optional — not required for multi-brand DOI

This org-wide setting is only for marketing unsubscribe and preference-center links. It is unrelated to double opt-in success redirects (those use per-template confirm_success_redirect_url and confirm_template). If you skip this setting, links use the ArtaMail default — which is fine for getting started.

Multiple products
Use a separate ArtaMail account per brand and set preferences_url_template on each account (e.g. https://prefs.superwidget.com/manage?token={{token}}). See the Multiple Products guide. For shared contacts in one account, see shared contacts (advanced).

Template variables

VariableReplaced with
{{unsubscribe_url}}Full preference URL (global token)
{{unsubscribe_<type_slug>}}Full URL scoped to a subscription type
{{unsubscribe_token}}Bare signed token — build your own URL in the template
{{unsubscribe_token_<type_slug>}}Bare typed token for a subscription type

Your domain must handle GET and POST

When you host preference links on your domain, you are responsible for two entry points. ArtaMail APIs stay the source of truth for token verification and consent updates.

GET — browser visits

Users click links in the email body. Your page should read the token from the query string or path, then load preference data from ArtaMail:

http
GET https://artamail.artatol.net/api/u/{token}/data

Response includes locale, resolved copy (all page strings for the contact's language), optional oneClickCopy, orgName (brand), legalEntityName, and localized subscription subtypes. Use copy.title, copy.button_save, etc. in your UI — or use ArtaMail custom HTML with placeholders like {{title}}. Full reference: Preferences Data API.

Example response

json
{
"orgId": "550e8400-e29b-41d4-a716-446655440000",
"orgName": "SuperWidget",
"legalEntityName": "Acme Holdings s.r.o.",
"email": "[email protected]",
"locale": "cs",
"copy": {
"title": "Předvolby e-mailu",
"subtitle": "Vyberte, jaké e-maily chcete dostávat.",
"footer": "Powered by ArtaMail",
"button_save": "Uložit předvolby",
"button_unsubscribe": "Odhlásit se ze všeho",
"type_title": "Předvolby e-mailu"
},
"oneClickCopy": {
"success_title": "Odhlášeno",
"success_message": "Byli jste odhlášeni z našeho seznamu."
},
"type": null,
"subtypes": [
{
"id": "subtype-uuid",
"slug": "weekly-digest",
"typeSlug": "newsletter",
"label": "Týdenní přehled",
"channel": "marketing",
"sortOrder": 0,
"subscribed": true
}
]
}

Subtype labels are already localized. Save changes with POST /api/u/{token}/preferences (subtype slugs as JSON keys).

POST — mail client one-click

Gmail and other clients send an RFC 8058 one-click unsubscribe POST to the URL in the List-Unsubscribe header — the same custom URL you configured. Your server must accept that POST and proxy it to ArtaMail:

http
POST https://artamail.artatol.net/api/u/{token}
Content-Type: application/x-www-form-urlencoded
List-Unsubscribe=One-Click
Do not skip the POST handler
If your custom URL only serves a GET landing page, one-click unsubscribe from mail clients will fail even though in-email links work. Optional: proxy POST with ?redirect=1 to show a localized success page at /preferences/{token}?one_click=1 (uses org one_click_copy).

ArtaMail hosted UI

Default landing after GET /api/u/{token} is /preferences/{token}. Legacy /unsubscribe/* URLs redirect permanently.

Custom HTML templates

On subscription types with custom HTML, wrap form-only sections (header, intro, footer) in artamail-form-only so they hide after save. Success content lives in #artamail-success inside {{subtypes_form}}. Optional post-save CTA: {{success_button}} or class artamail-success-cta ({{success_button_class}}). Injected and {{success_button}} links use target="_top" so navigation leaves the hosted iframe. If you build your own <a> with {{success_button_href}}, add target="_top" as well.

Example reverse proxy (Node)

prefs-proxy.ts
// POST /manage?token=... → ArtaMail one-click unsubscribe
export async function POST(req: Request) {
const token = new URL(req.url).searchParams.get('token');
if (!token) return new Response('Missing token', { status: 400 });
const body = await req.text();
const res = await fetch(`https://artamail.artatol.net/api/u/${token}`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body,
});
return new Response(null, { status: res.ok ? 200 : res.status });
}