Prenumerationslistor
Subscription lists let people sign up for your newsletters and sendouts. Lists are created and managed in Memlist, and there are two ways to put a signup on your own website:
- Link to the hosted form — every list has a ready-made public page. No code required.
- Build your own form — a public JSON API lets you implement the signup and unsubscribe flow entirely in your own design.
There is also an authenticated admin API for creating and managing lists and subscribers.
Option 1 — Link to the hosted form
Every subscription list has a public form hosted by your Memlist instance:
https://<instance>.memlist.se/subscribe/<list_uuid>
The page renders the list's name, description, image, fields, optional questions and consent checkbox, and handles the subscription for you. Link to it or embed it in an iframe.
You find the list's uuid in Memlist where the list is managed, or via the admin API
(GET /subscription_list/{id}).
Option 2 — Build your own form
The public endpoints require no authentication. Base URL:
https://<instance>.memlist.se/api/v3
GET /subscription_list/public/{uuid}
Fetch the list's public info — use it to render your form.
curl -s "https://<instance>.memlist.se/api/v3/subscription_list/public/<list_uuid>"
Response — 200 OK:
{
"name": "Nyhetsbrev",
"description": "Vårt månatliga nyhetsbrev.",
"fields": ["firstname", "lastname"],
"uuid": "9c1b2f4e-77aa-4f0c-9a41-2f8d0c3e5b21",
"image_url": null,
"show_image": false,
"design": null,
"term": { "id": 12, "name": "Samtycke", "html": "<p>...</p>" },
"questions": [
{
"prop_id": 44,
"name": "Intresserad av evenemang",
"descr": "Få inbjudningar till våra evenemang",
"group_name": "Intressen",
"group_descr": null
}
]
}
fields— which optional fields the form should show (firstname,lastname,phone).emailis always required.term— an optional consent text configured on the list, ornull. If present, show it with a checkbox and sendterms_accepted: truewhen the visitor accepts.questions— optional checkboxes configured on the list. Send the ids the visitor ticked asanswered_prop_ids.
Returns 404 if the list does not exist or is inactive.
POST /subscription_list/public/{uuid}
Subscribe a visitor to the list.
curl -s -X POST "https://<instance>.memlist.se/api/v3/subscription_list/public/<list_uuid>" \
-H 'Content-Type: application/json' \
-d '{
"email": "anna@example.com",
"firstname": "Anna",
"lastname": "Andersson",
"answered_prop_ids": [44],
"terms_accepted": true
}'
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Max 254 characters |
firstname | string | No | Max 128 characters |
lastname | string | No | Max 128 characters |
phone | string | No | Max 64 characters |
answered_prop_ids | number[] | No | Ids of ticked questions from the list's questions |
terms_accepted | boolean | No | Send true when the visitor accepted the list's term |
Response — 201 Created:
{ "member_id": 12345, "subscription": { "...": "..." } }
What happens on the Memlist side:
- If a member with that email already exists in the list's organization, they are subscribed (re-subscribing is always allowed). Otherwise a new member is created.
- Ticked questions are stored as attributes on the member — only ids that actually belong to the list's configured question set are accepted.
- If the list has a consent text and
terms_accepted: truewas sent, the acceptance is recorded on the member under Samtycken.
Errors:
| Status | Body | When |
|---|---|---|
400 | validation payload | Missing or invalid email |
404 | { "reason": "list not found" } | Unknown or inactive list |
429 | { "reason": "subscription temporarily unavailable" } | The list's subscriber cap was reached |
GET /subscription_list/public/company/{company_id}
Lists an organization's active subscription lists — useful when you want to offer several opt-ins at once.
Response — 200 OK:
[
{ "id": 3, "name": "Nyhetsbrev", "description": "Vårt månatliga nyhetsbrev." },
{ "id": 7, "name": "Evenemang", "description": null }
]
Note that this endpoint intentionally returns no uuid — take the uuids for your
signup forms from Memlist or the admin API.
Unsubscribe
Sendouts from Memlist already include working unsubscribe links, so if you only use the API to collect subscribers you do not need to implement anything here.
For a custom flow there are two public endpoints:
GET /subscription_list/unsubscribe/{list_uuid}/{member_uuid}— renders a hosted confirmation page. The GET itself never changes anything (so email security scanners cannot unsubscribe people by prefetching the link); the state change happens when the visitor clicks the confirm button.POST /subscription_list/unsubscribe/{list_uuid}/{member_uuid}— unsubscribes the member from that list. The response is always a generic{ "ok": true }, regardless of whether the member or list existed, so the endpoint cannot be used to probe who is subscribed.
There is also a global opt-out variant (POST /subscription_list/unsubscribe/all/{member_uuid})
that removes the member from all future sendouts. It requires a signed token
that only Memlist's own sendout links carry — a custom implementation should use the
per-list variant above.
Rate limits
| Endpoints | Limit |
|---|---|
Public GET endpoints | 120 requests per minute per IP |
Public POST endpoints | 20 requests per minute per IP |
Admin API
Managing lists requires an access token — see Authentication — and an access group that includes the subscription list module.
| Method | Path | Purpose |
|---|---|---|
GET | /subscription_list?company_id={company_id} | List an organization's subscription lists |
GET | /subscription_list/{id} | Get one list, including its uuid |
POST | /subscription_list | Create a list — name and company_id required; optional description, fields |
PUT | /subscription_list/{id} | Update name, description, fields, is_active and the list's image, design, consent term and questions |
DELETE | /subscription_list/{id} | Delete a list |
GET | /subscription_list/{id}/subscribers | List the list's subscribers |
GET | /subscription_list/member/{member_id} | The member's available lists with an is_subscribed flag |
POST | /subscription_list/{id}/subscribe/{member_id} | Subscribe a member |
POST | /subscription_list/{id}/unsubscribe/{member_id} | Unsubscribe a member |
Example: a minimal custom form
const HOST = 'https://<instance>.memlist.se';
const LIST_UUID = '9c1b2f4e-77aa-4f0c-9a41-2f8d0c3e5b21';
// 1. Fetch the list info and render your form from it.
const info = await fetch(`${HOST}/api/v3/subscription_list/public/${LIST_UUID}`)
.then(r => r.json());
// 2. Subscribe on submit.
async function subscribe(form_values) {
const res = await fetch(`${HOST}/api/v3/subscription_list/public/${LIST_UUID}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: form_values.email,
firstname: form_values.firstname,
lastname: form_values.lastname,
terms_accepted: form_values.terms_accepted === true
})
});
if (res.status === 201) return true;
const err = await res.json().catch(() => ({}));
throw new Error(err.reason || `subscribe failed: ${res.status}`);
}