MyPlace API

Integrate guest data and receive real-time event notifications from your venues.

Base URL https://api.myplaceconnect.net

Authentication

All requests require an API key in the x-api-key header.

curl -H "x-api-key: YOUR_API_KEY" \
  https://api.myplaceconnect.net/v1/guests

Create keys in Account > Developers > API Keys. Maximum 3 per venue.

Rate Limits

Rate limits are applied per API key. Two policies are enforced simultaneously:

PolicyLimitWindow
BURST100 requests10 seconds
DAILY100,000 requests24 hours

Exceeding either limit returns 429 Too Many Requests:

{
  "status": "error",
  "message": "Too many requests, please try again later",
  "errorType": "RATE_LIMIT",
  "policyName": "BURST"
}

The policyName field indicates which limit was hit (BURST or DAILY).

Every response includes RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, and RateLimit-Policy headers reflecting the currently binding policy. Use them to pace requests proactively. On a 429, Retry-After tells you when to retry.

Error Codes

StatusMeaning
200Success
201Created
400Bad Request — missing or invalid fields
401Unauthorized — invalid or missing API key
404Not Found
429Too Many Requests
500Internal Server Error

Guest Object

FieldTypeDescription
emailstringPrimary identifier (unique per venue)
firstNamestringGuest's first name
lastNamestringGuest's last name
phoneNumberstringPhone number (E.164 format recommended)
genderstringM, F, or other
countrystringISO 3166-1 alpha-2 country code
over18booleanAge verification flag
over21booleanAge verification flag (US)
tagsstring[]Custom labels (appended on update, not replaced)
visitFrequencyintegerNumber of visits to venue
first_seenstringFirst visit timestamp
last_seenstringMost recent visit timestamp
languagestringDetected device language
locationsobject[]Venues the guest has visited
devicesstring[]MAC addresses of guest's devices
subscribedToobject[]Integration subscription status (MailChimp, etc.)

List Guests

GET/v1/guests
ParameterTypeDefaultDescription
pageinteger1Page number (1-based)
per_pageinteger10Results per page (max 1000)
offsetinteger0Legacy — used only if page is not provided
limitinteger10Legacy — used only if per_page is not provided

Response 200

{
  "status": "OK",
  "data": [
    {
      "email": "john@example.com",
      "firstName": "John",
      "lastName": "Doe",
      "phoneNumber": "+353851234567",
      "gender": "M",
      "over18": true,
      "tags": ["vip"],
      "visitFrequency": 5
    }
  ],
  "metadata": {
    "total_results": 150,
    "page": 1,
    "per_page": 10
  }
}

Get Guest

GET/v1/guests/{email}

Returns a single guest by email address.

Response 200

{
  "status": "OK",
  "data": {
    "email": "john@example.com",
    "firstName": "John",
    "lastName": "Doe",
    "phoneNumber": "+353851234567",
    "gender": "M",
    "country": "IE",
    "over18": true,
    "tags": ["vip", "regular"],
    "visitFrequency": 5,
    "first_seen": "15/01/2024, 10:30",
    "last_seen": "27/04/2026, 14:15"
  }
}

Create Guest

POST/v1/guests
FieldTypeRequired
emailstringYes
firstNamestringNo
lastNamestringNo
phoneNumberstringNo
over18booleanNo
genderstringNo
countrystringNo
tagsstring[]No

Request

{
  "email": "john@example.com",
  "firstName": "John",
  "lastName": "Doe",
  "phoneNumber": "+353851234567",
  "over18": true,
  "gender": "M",
  "country": "IE",
  "tags": ["imported"]
}

Response 201

{
  "message": "Guest created successfully",
  "guestId": "john@example.com",
  "data": { ... }
}

Update Guest

PUT/v1/guests/{email}

Partial updates supported. Tags are appended, not replaced.

Request

{
  "firstName": "Jonathan",
  "tags": ["vip"]
}

Response 200

{
  "message": "Guest updated successfully",
  "guestId": "john@example.com",
  "data": {
    "email": "john@example.com",
    "firstName": "Jonathan",
    "lastName": "Doe",
    "tags": ["regular", "vip"]
  }
}

Delete Guest

DELETE/v1/guests/{email}

Permanently removes a guest from your venue.

Response 200

{
  "message": "Guest with id: john@example.com deleted",
  "status": true
}

Unsubscribe Guest

GET/v1/guests/unsubscribe/{email}

Removes marketing consent and triggers removal from connected integrations (MailChimp, Klaviyo, etc.).

Response 200

{
  "message": "Guest john@example.com unsubscribed successfully",
  "status": true
}

Webhooks

Webhooks send real-time HTTP POST notifications to your server when events occur in your venue. Instead of polling the API, your server gets notified automatically.

MethodPOST
Content-Typeapplication/json
Timeout10 seconds
Retries3 attempts (2s, 4s backoff)
HeadersX-MyPlace-Signature, X-MyPlace-Event

Setup

1
Create endpoint

Go to Account > Developers > Webhooks and click Add Endpoint.

2
Configure

Enter your HTTPS URL, select events, and choose a venue.

3
Copy signing secret

After saving, a signing secret is displayed once. Copy it immediately.

Events

EventTriggerDescription
user_addedNew guest registersGuest connects to WiFi and completes registration
user_removedGuest removedGuest is deleted from your venue
user_returnedReturning guestPreviously registered guest connects again

Payloads

user_added / user_returned

{
  "eventName": "User added",
  "data": {
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@example.com",
    "firstVisit": "2024-01-15",
    "lastVisit": "2024-04-27",
    "marketingAccepted": true,
    "visitFrequency": 5,
    "language": "en",
    "gender": "M",
    "over18": true,
    "tags": ["vip", "regular"]
  },
  "created": 1714239450
}

user_removed

{
  "eventName": "User removed",
  "data": {
    "userId": "john@example.com",
    "deleted_at": 1714239450
  },
  "created": 1714239450
}

Verifying Signatures

Every webhook includes an X-MyPlace-Signature header — an HMAC-SHA256 hash of the request body signed with your webhook secret.

Signature verification is optional but recommended to ensure requests are genuinely from MyPlace.
const crypto = require('crypto');

function verifyWebhook(req, secret) {
  const signature = req.headers['x-myplace-signature'];
  const body = JSON.stringify(req.body);
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return signature === expected;
}

app.post('/webhook', express.json(), (req, res) => {
  if (!verifyWebhook(req, process.env.MYPLACE_WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  const { eventName, data } = req.body;
  console.log(`Received ${eventName}:`, data);
  res.status(200).json({ received: true });
});
import hmac, hashlib

def verify_webhook(body, signature, secret):
    expected = hmac.new(
        secret.encode(), body.encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    sig = request.headers.get('X-MyPlace-Signature')
    if not verify_webhook(request.get_data(as_text=True), sig, SECRET):
        return jsonify({'error': 'Invalid signature'}), 401
    event = request.json
    return jsonify({'received': True})
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_MYPLACE_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $payload, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$event = json_decode($payload, true);

Testing

Click the Test button next to your webhook in the admin panel. A signed test payload is sent:

{
  "eventName": "test",
  "data": {
    "message": "This is a test webhook from MyPlace",
    "webhookId": "abc-123",
    "timestamp": 1714239450000
  },
  "created": 1714239450
}

Test events appear in delivery logs and can be used to verify your endpoint and signature validation.

Best Practices

Respond fast — return 200 OK within 10 seconds. Process webhook data asynchronously.