Skip to content
Mitgliederbuch Developers

Quickstart

Four steps from a key to a working integration. Allow ten minutes.

1. Create a key

An administrator of the association creates keys in Mitgliederbuch under Settings → API keys → New key. Give the key a name that tells you later what it is for, and choose its scopes. By default everything is read-only; for step 4 you also need leden:schrijven.

The key is shown once. Put it in an environment variable, not in your code:

shell
export LEDENBOEK_API_KEY="lb_test_..."

In a sample association the key starts with lb_test_. No email and no payment requests are sent there, so you can try everything without touching real members.

2. Your first request

GET /v2/organization works with any key and returns the association, the modules it has enabled and the scopes of your key. A good first check that everything is set up.

curl https://api.mitgliederbuch.de/v2/organization \
  -H "Authorization: Bearer $LEDENBOEK_API_KEY"

The response:

200 OK
{
  "object": "organization",
  "id": 42,
  "name": "WSV De Kaag",
  "slug": "wsv-de-kaag",
  "country": "Nederland",
  "language": "nl",
  "website_url": "https://www.wsvdekaag.nl",
  "modules": {
    "groups": true,
    "committees": true,
    "participants": false,
    "relationships": false,
    "events": true,
    "invoicing": true
  },
  "api_key": {
    "name": "Website integration",
    "prefix": "lb_test_8kQz",
    "environment": "test",
    "scopes": [
      "leden:lezen",
      "leden:schrijven"
    ]
  }
}

A 401 usually means the header is not exactly Authorization: Bearer lb_.... A 402 means the association has no valid subscription.

3. Page through members

With the leden:lezen scope you fetch members with GET /v2/members. Lists come in pages of up to 100 records (25 by default). As long as has_more is true, request the next page by passing next_cursor as starting_after.

curl "https://api.mitgliederbuch.de/v2/members?limit=100" \
  -H "Authorization: Bearer $LEDENBOEK_API_KEY"

# Next page: pass next_cursor from the previous response
curl "https://api.mitgliederbuch.de/v2/members?limit=100&starting_after=1234" \
  -H "Authorization: Bearer $LEDENBOEK_API_KEY"

A page looks like this (shortened; all fields are in the reference):

200 OK
{
  "object": "list",
  "data": [
    {
      "object": "member",
      "id": 1234,
      "membership_number": "L042",
      "first_name": "Anna",
      "last_name": "de Vries",
      "email": "anna@example.com",
      "status": "active",
      "member_since": "2024-03-01",
      "created_at": "2024-03-01T10:12:00+01:00",
      "updated_at": "2026-10-02T08:30:00+02:00"
    }
  ],
  "has_more": true,
  "next_cursor": "1234"
}

4. Create a member

With leden:schrijven you create a member with POST /v2/members. Send an Idempotency-Key: a unique value per new member, such as a UUID. If the connection drops and you send the same request again with the same key, you get the first response back and the member is not created twice.

curl https://api.mitgliederbuch.de/v2/members \
  -X POST \
  -H "Authorization: Bearer $LEDENBOEK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2a3e-8d4b-4c1e-9a7f-2b5d0e9c4a11" \
  -d '{"first_name": "Anna", "last_name": "de Vries", "email": "anna@example.com"}'

If a field is invalid, you get a 422 that says what is wrong per field:

422 Unprocessable Entity
{
  "type": "https://developers.mitgliederbuch.de/errors/validation_failed",
  "title": "Validation failed",
  "status": 422,
  "detail": "One or more fields are invalid; see errors.",
  "instance": "/v2/members",
  "errors": [
    {
      "field": "email",
      "code": "invalid",
      "message": "Email is invalid"
    }
  ]
}

Next steps