# MRSHL

Use the MRSHL integration to export Eventication visitor and member data (lists, members, check-in status, wristband codes) to [MRSHL](https://www.mrshl.be) for F\&B operations.

### Setup in Eventication

Go to: `Admin → Event → General → Integrations → + (button) → MRSHL`. If you can't find it, ask an Eventication admin to enable the MRSHL module for your event.

{% hint style="info" %}
A MRSHL API key is scoped to an event. Each event needs its own MRSHL integration.
{% endhint %}

### Configuring access

After creating the integration, click the **edit** button to configure which data MRSHL can access:

* **Memberships**: toggle on/off to allow access to the members endpoint.
* **Lists**: select which lists MRSHL can access. Only selected lists will be returned by the lists endpoint. If no lists are selected, the lists endpoint will return `403 Access denied`.

{% hint style="warning" %}
Review your access settings carefully. Only grant access to lists and members that MRSHL needs for their F\&B operations.
{% endhint %}

### API key / authentication

You'll see an **API key** in the MRSHL integration screen. Keep this key **secret** (treat it like a password):

* Do not share it
* Do not commit it to git
* Do not paste it in screenshots / tickets
* Store it in your secret manager or encrypted environment variables

Authenticate every request with the Authorization Bearer header:

```http
Authorization: Bearer YOUR_MRSHL_API_KEY
```

### Base URL

All endpoints are hosted on the API domain:

* `https://api.eventication.com`

Example:

* `https://api.eventication.com/mrshl/lists`

### Pagination

List endpoints are paginated to keep responses fast.

* Query param: `page` (1-based)
* Fixed page size: **100 objects per request**
* The response includes `meta`:
  * `page`, `per_page`, `total_pages`, `total_count`, `next_page`, `prev_page`

Example:

* `GET https://api.eventication.com/mrshl/lists?page=2`

### Rate limiting

Requests are rate-limited:

* **10** requests per minute
* On limit: [HTTP 429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429) with `{ "error": "Rate limit exceeded" }`

***

### Endpoints

#### <mark style="color:$success;">GET</mark> `/mrshl/lists`

Returns list visitors across all accessible lists for the event, including check-in status and wristband codes.

* URL: `https://api.eventication.com/mrshl/lists?page=1`
* Access: requires at least one list to be selected in the integration settings.
* Fields per item:
  * `list_id` — encoded list identifier
  * `list_name` — name of the list
  * `list_entry_id` — encoded list entry identifier
  * `list_entry_name` — name of the responsible person on the list entry
  * `visitor_id` — encoded visitor (list entry item) identifier
  * `visitor_firstname` — visitor's first name
  * `visitor_lastname` — visitor's last name
  * `visitor_email` — visitor's email address
  * `last_checkin_at` — last check-in timestamp (ISO 8601), or `null`
  * `last_checkout_at` — last check-out timestamp (ISO 8601), or `null`
  * `valid_wristband_codes` — array of active wristband codes for this visitor

Response shape:

```json
{
  "data": [
    {
      "list_id": "Z2lkOi8vZXZlbnRpY2F0aW9uL0xpc3QvODYy",
      "list_name": "VIP Guests",
      "list_entry_id": "Z2lkOi8vZXZlbnRpY2F0aW9uL0xpc3RFbnRyeS83NTI",
      "list_entry_name": "John Doe",
      "visitor_id": "Z2lkOi8vZXZlbnRpY2F0aW9uL0xpc3RFbnRyeUl0ZW0vMjIw",
      "visitor_firstname": "John",
      "visitor_lastname": "Doe",
      "visitor_email": "john.doe@example.com",
      "last_checkin_at": "2026-03-15T14:30:00+01:00",
      "last_checkout_at": null,
      "valid_wristband_codes": [
        "igJYuGHKbUgdbmX6UDFD",
        "CxfxKq0THi7OAx1oda0x"
      ]
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 100,
    "total_pages": 3,
    "total_count": 296,
    "next_page": 2,
    "prev_page": null
  }
}
```

#### <mark style="color:$success;">GET</mark> `/mrshl/memberships`

Returns members for the event, including check-in status and wristband codes.

* URL: `https://api.eventication.com/mrshl/memberships?page=1`
* Access: requires the memberships toggle to be enabled in the integration settings.
* Fields per item:
  * `visitor_id` — encoded membership identifier
  * `visitor_firstname` — member's first name
  * `visitor_lastname` — member's last name
  * `visitor_email` — member's email address
  * `last_checkin_at` — last check-in timestamp (ISO 8601), or `null`
  * `last_checkout_at` — last check-out timestamp (ISO 8601), or `null`
  * `valid_wristband_codes` — array of active wristband codes for this member

Response shape:

```json
{
  "data": [
    {
      "visitor_id": "Z2lkOi8vZXZlbnRpY2F0aW9uL01lbWJlcnNoaXAvMjIw",
      "visitor_firstname": "Jane",
      "visitor_lastname": "Smith",
      "visitor_email": "jane.smith@example.com",
      "last_checkin_at": "2026-03-15T12:00:00+01:00",
      "last_checkout_at": "2026-03-15T18:30:00+01:00",
      "valid_wristband_codes": [
        "7RqazTG6pq3RqTIZME3P",
        "eFpmkZbqX1ZHofUzHMSX",
        "O7VgaD2YFOkBtoPIJplC"
      ]
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 100,
    "total_pages": 1,
    "total_count": 42,
    "next_page": null,
    "prev_page": null
  }
}
```

***

### Errors & status codes

[401 Unauthorized](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401)

* Missing/invalid API key or integration disabled
* Example: `{ "error": "Integration not found. Request UUID: ..." }`

[403 Forbidden](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403)

* Endpoint access not enabled for this integration
* Example: `{ "error": "Access denied" }`

[429 Too Many Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429)

* Rate limit exceeded
* Example: `{ "error": "Rate limit exceeded" }`

***

### Example clients

#### cURL

```bash
curl -sS "https://api.eventication.com/mrshl/lists?page=1" \
  -H "Authorization: Bearer YOUR_MRSHL_API_KEY" \
  -H "Accept: application/json"
```

#### Ruby (Net::HTTP)

```ruby
require 'json'
require 'net/http'
require 'uri'

API_KEY = 'YOUR_MRSHL_API_KEY'
BASE_URL = 'https://api.eventication.com'

def get_json(path, page:)
  uri = URI("#{BASE_URL}#{path}?page=#{page}")
  req = Net::HTTP::Get.new(uri)
  req['Authorization'] = "Bearer #{API_KEY}"
  req['Accept'] = 'application/json'

  res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
  raise "HTTP #{res.code}: #{res.body}" unless res.is_a?(Net::HTTPSuccess)

  JSON.parse(res.body)
end

# Fetch all visitors across accessible lists (paginated)
page = 1
loop do
  payload = get_json('/mrshl/lists', page: page)
  payload.fetch('data').each do |v|
    puts "#{v['visitor_firstname']} #{v['visitor_lastname']} <#{v['visitor_email']}> — #{v['valid_wristband_codes'].size} wristband(s)"
  end

  next_page = payload.dig('meta', 'next_page')
  break if next_page.nil?
  page = next_page
end
```

#### JavaScript (fetch)

```javascript
const apiKey = 'YOUR_MRSHL_API_KEY';
const baseUrl = 'https://api.eventication.com';

async function fetchPage(path, page) {
  const res = await fetch(`${baseUrl}${path}?page=${page}`, {
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Accept': 'application/json',
    },
  });

  if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
  return await res.json();
}

// Fetch all memberships
let page = 1;
while (true) {
  const payload = await fetchPage('/mrshl/memberships', page);
  for (const m of payload.data) {
    console.log(m.visitor_firstname, m.visitor_lastname, m.valid_wristband_codes);
  }
  if (!payload.meta.next_page) break;
  page = payload.meta.next_page;
}
```

#### Python (requests)

```python
import requests

api_key = "YOUR_MRSHL_API_KEY"
base_url = "https://api.eventication.com"

page = 1
while True:
    r = requests.get(
        f"{base_url}/mrshl/lists",
        params={"page": page},
        headers={"Authorization": f"Bearer {api_key}", "Accept": "application/json"},
        timeout=30,
    )
    r.raise_for_status()
    payload = r.json()

    for row in payload["data"]:
        codes = ", ".join(row["valid_wristband_codes"])
        print(f"{row['visitor_firstname']} {row['visitor_lastname']} — wristbands: {codes}")

    if payload["meta"]["next_page"] is None:
        break
    page = payload["meta"]["next_page"]
```

{% hint style="info" %}
This API is a work in progress BETA and might change over time.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.eventication.com/event/general/integrations/mrshl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
