Hoppa till huvudinnehåll

Memlist API Documentation

Authentication

Memlist uses OAuth 2.0 Client Credentials for API access. All API endpoints are available at:

https://<instance>.memlist.se/api/v3/

Getting Started

  1. Contact your Memlist administrator to generate API credentials
  2. You will receive a client_id and client_secret
  3. Use these to obtain access tokens as described below

Obtaining an Access Token

Endpoint: POST /api/v3/access/user/basic

Authentication: HTTP Basic Auth with client_id as username and client_secret as password.

Request

curl -X POST https://<instance>.memlist.se/api/v3/access/user/basic \
-H "Authorization: Basic <base64(client_id:client_secret)>"

Example (with inline base64 encoding):

curl -X POST https://<instance>.memlist.se/api/v3/access/user/basic \
-H "Authorization: Basic $(echo -n 'your-client-id:your-client-secret' | base64)"

Response

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_expires_ts": 1743465600
}
FieldTypeDescription
access_tokenstringJWT token used to authenticate API requests
token_typestringAlways "Bearer"
expires_innumberToken lifetime in seconds
refresh_tokenstringToken used to obtain a new access token without re-authenticating
refresh_expires_tsnumberUnix timestamp when the refresh token expires

Error Responses

StatusReasonDescription
401Missing or invalid Authorization headerNo Basic auth header provided
401invalid "Basic" credentialsCould not parse client_id and client_secret
401provided client_id and client_secret does not match any recordCredentials not found
429Too Many RequestsRate limit exceeded (max 10 requests per minute)

Using the Access Token

Include the access token in the Authorization header for all API requests:

curl https://<instance>.memlist.se/api/v3/<endpoint> \
-H "Authorization: Bearer <access_token>"

Example: List members

curl https://<instance>.memlist.se/api/v3/member \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Refreshing an Access Token

When the access token expires, use the refresh token to obtain a new one without re-entering credentials.

Endpoint: POST /api/v3/access/user/oauth/refresh_token

Request

curl -X POST https://<instance>.memlist.se/api/v3/access/user/oauth/refresh_token \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}'

Response

{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_expires_ts": 1743465600
}

A new refresh token is returned on each refresh (token rotation). Always store and use the latest refresh token.

Error Responses

StatusReasonDescription
400Missing fieldrefresh_token field not provided
401expiredRefresh token has expired. Re-authenticate with client credentials.
403forbiddenInvalid refresh token
429Too Many RequestsRate limit exceeded (max 20 requests per minute)

Token Lifecycle

1. Authenticate with client_id + client_secret
POST /access/user/basic
|
v
2. Receive access_token + refresh_token
|
v
3. Use access_token for API calls
Authorization: Bearer <access_token>
|
v
4. When access_token expires (401 "expired")
|
v
5. Use refresh_token to get new tokens
POST /access/user/oauth/refresh_token
|
v
6. Receive new access_token + new refresh_token
(go to step 3)
|
v
7. When refresh_token expires
(go to step 1)

Rate Limits

EndpointLimit
POST /access/user/basic10 requests per minute per IP
POST /access/user/oauth/refresh_token20 requests per minute per IP

When rate limited, the API returns HTTP 429 Too Many Requests.


Common API Endpoints

Once authenticated, the following endpoints are available. All requests require the Authorization: Bearer <access_token> header.

Members

MethodEndpointDescription
GET/memberList members
GET/member/{id}Get member by ID
POST/memberCreate member
PUT/member/{id}Update member
DELETE/member/{id}Delete member

Events

MethodEndpointDescription
GET/events/list?company_id={id}List events for a company
GET/events/{id}Get event by ID
POST/eventsCreate event
PUT/events/{id}Update event
DELETE/events/{id}Delete event

Company

MethodEndpointDescription
GET/companyGet current company
GET/company/hierarchyGet company hierarchy

Periods

MethodEndpointDescription
GET/company_periodList company periods

Member Types

MethodEndpointDescription
GET/membertypeList member types

Properties / Attributes

MethodEndpointDescription
GET/propertyList properties
MethodEndpointDescription
POST/market/members/searchSearch members with filters

Search Request Body:

{
"filters": {
"member_variables": {
"email": "EXISTS",
"statuses": ["MEMBER"],
"age_from": 18,
"age_to": 65
},
"companies": {
"company_ids": ["abc123"],
"include": "ANY"
},
"events": {
"event_ids": [1, 2],
"include": "ANY"
},
"properties": {
"prop_ids": [10, 20],
"include": "ANY"
}
},
"page": 1,
"limit": 100,
"sort_by": "created_desc",
"search_text": ""
}

Search Response:

{
"members": [ ... ],
"count": 122,
"page": 1,
"limit": 100
}

Error Handling

All error responses follow this format:

{
"reason": "description of the error"
}

Common HTTP Status Codes

StatusDescription
200Success
201Created
400Bad request (missing or invalid fields)
401Unauthorized (token expired or missing)
403Forbidden (insufficient permissions)
404Not found
422Invalid token
429Rate limit exceeded
500Internal server error

Handling Token Expiry

When a token expires, the API returns:

{
"error": "expired",
"context": "user"
}

Your application should catch 401 responses and automatically refresh the token using the refresh endpoint.


Code Examples

Node.js

const axios = require('axios');

const BASE_URL = 'https://<instance>.memlist.se/api/v3';
const CLIENT_ID = 'your-client-id';
const CLIENT_SECRET = 'your-client-secret';

let access_token = null;
let refresh_token = null;

async function authenticate() {
const credentials = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
const res = await axios.post(`${BASE_URL}/access/user/basic`, null, {
headers: { Authorization: `Basic ${credentials}` }
});
access_token = res.data.access_token;
refresh_token = res.data.refresh_token;
}

async function refresh() {
const res = await axios.post(`${BASE_URL}/access/user/oauth/refresh_token`, {
refresh_token
});
access_token = res.data.access_token;
refresh_token = res.data.refresh_token;
}

async function api_call(method, path, data) {
try {
const res = await axios({
method,
url: `${BASE_URL}${path}`,
data,
headers: { Authorization: `Bearer ${access_token}` }
});
return res.data;
} catch (err) {
if (err.response?.status === 401) {
await refresh();
return api_call(method, path, data);
}
throw err;
}
}

// Usage
async function main() {
await authenticate();
const members = await api_call('get', '/member');
console.log(members);
}

main();

Python

import requests
import base64

BASE_URL = 'https://<instance>.memlist.se/api/v3'
CLIENT_ID = 'your-client-id'
CLIENT_SECRET = 'your-client-secret'

class MemlistAPI:
def __init__(self):
self.access_token = None
self.refresh_token = None

def authenticate(self):
credentials = base64.b64encode(
f'{CLIENT_ID}:{CLIENT_SECRET}'.encode()
).decode()
res = requests.post(
f'{BASE_URL}/access/user/basic',
headers={'Authorization': f'Basic {credentials}'}
)
res.raise_for_status()
data = res.json()
self.access_token = data['access_token']
self.refresh_token = data['refresh_token']

def refresh(self):
res = requests.post(
f'{BASE_URL}/access/user/oauth/refresh_token',
json={'refresh_token': self.refresh_token}
)
res.raise_for_status()
data = res.json()
self.access_token = data['access_token']
self.refresh_token = data['refresh_token']

def request(self, method, path, **kwargs):
headers = {'Authorization': f'Bearer {self.access_token}'}
res = requests.request(method, f'{BASE_URL}{path}', headers=headers, **kwargs)
if res.status_code == 401:
self.refresh()
headers = {'Authorization': f'Bearer {self.access_token}'}
res = requests.request(method, f'{BASE_URL}{path}', headers=headers, **kwargs)
res.raise_for_status()
return res.json()

# Usage
api = MemlistAPI()
api.authenticate()
members = api.request('GET', '/member')
print(members)

cURL

# 1. Authenticate
TOKEN=$(curl -s -X POST https://<instance>.memlist.se/api/v3/access/user/basic \
-H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
| jq -r '.access_token')

# 2. Make API calls
curl https://<instance>.memlist.se/api/v3/member \
-H "Authorization: Bearer $TOKEN"

Support

For API support, contact your Memlist administrator or reach out at support@memlist.se.