Project: "Where Has Benny Been?" - API Documentation
Base URL: https://hooks.mad-monkey-creations.com
Description: Log QR code scan and redirect to landing page
| Parameter | Type | Required | Description |
|---|---|---|---|
| qr_id | string | Yes | Card ID (e.g., "T42", "N123") |
X-Forwarded-For or X-Real-IP - Client IP addressUser-Agent - Browser/device informationReferer - Previous page URL (if available)curl -L "https://hooks.mad-monkey-creations.com/scan?qr_id=T42"
HTTP 302 Redirect to: https://mad-monkey-creations.com/benny?qr_id=T42
scans tablecards.last_scan_ts and increment total_scans| Error | HTTP Code | Response |
|---|---|---|
| Missing qr_id | 400 | {"error": "Missing qr_id parameter"} |
| Invalid qr_id | 404 | {"error": "Card not found"} |
| Database error | 500 | {"error": "Internal server error"} |
Description: Process contest entry form submission
{
"qr_id": "T42",
"email": "user@example.com",
"name": "John Doe",
"user_city": "Chicago, IL",
"consent": true,
"captcha_token": "optional-captcha-token"
}
| Field | Type | Required | Validation |
|---|---|---|---|
| qr_id | string | Yes | Must exist in cards table |
| string | Yes | Valid email format | |
| name | string | No | Max 100 characters |
| user_city | string | Yes | Max 100 characters |
| consent | boolean | Yes | Must be true |
curl -X POST https://hooks.mad-monkey-creations.com/entry \
-H "Content-Type: application/json" \
-d '{
"qr_id": "T42",
"email": "user@example.com",
"name": "John Doe",
"user_city": "Chicago, IL",
"consent": true
}'
{
"success": true,
"message": "Entry submitted! Check your email to confirm.",
"entry_id": 12345
}
entries table (verified=false)| Error | HTTP Code | Response |
|---|---|---|
| Invalid email format | 400 | {"error": "Invalid email address"} |
| Missing consent | 400 | {"error": "Consent required"} |
| Rate limit exceeded | 429 | {"error": "Too many entries, please try again later"} |
| Duplicate entry (same month) | 409 | {"error": "You've already entered this month"} |
Description: Handle Listmonk webhook on subscriber confirmation
{
"event": "subscriber.confirmed",
"subscriber": {
"id": 123,
"email": "user@example.com",
"name": "John Doe",
"status": "enabled",
"lists": [1]
}
}
entries.verified=true for emailverified_at timestampusers table with confirmed status{
"success": true,
"message": "Subscriber confirmed"
}
Base URL: http://10.0.0.250:8081 (internal) or https://admin.mmlnk.us/rest (external, IP-restricted)
API Version: v3
X-Api-Key header
Description: List all short URLs
curl -X GET "http://10.0.0.250:8081/rest/v3/short-urls" \ -H "X-Api-Key: your-api-key-here"
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| itemsPerPage | integer | Items per page (default: 10) |
| searchTerm | string | Filter by short code or long URL |
| tags[] | array | Filter by tags |
{
"shortUrls": {
"data": [
{
"shortCode": "T42",
"shortUrl": "https://mmlnk.us/T42",
"longUrl": "https://hooks.mad-monkey-creations.com/scan?qr_id=T42",
"dateCreated": "2024-12-01T10:30:00Z",
"visitsCount": 42,
"tags": ["benny", "traveler"],
"domain": "mmlnk.us"
}
],
"pagination": {
"currentPage": 1,
"pagesCount": 10,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 95
}
}
}
Description: Create a new short URL
{
"longUrl": "https://hooks.mad-monkey-creations.com/scan?qr_id=T42",
"customSlug": "T42",
"domain": "mmlnk.us",
"tags": ["benny", "traveler"],
"title": "Benny Traveler Card 42",
"findIfExists": true
}
curl -X POST "http://10.0.0.250:8081/rest/v3/short-urls" \
-H "X-Api-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"longUrl": "https://hooks.mad-monkey-creations.com/scan?qr_id=T42",
"customSlug": "T42",
"domain": "mmlnk.us",
"tags": ["benny", "traveler"]
}'
{
"shortCode": "T42",
"shortUrl": "https://mmlnk.us/T42",
"longUrl": "https://hooks.mad-monkey-creations.com/scan?qr_id=T42",
"dateCreated": "2024-12-01T10:30:00Z",
"tags": ["benny", "traveler"],
"domain": "mmlnk.us"
}
Description: Get visit statistics for a short URL
curl -X GET "http://10.0.0.250:8081/rest/v3/short-urls/T42/visits" \ -H "X-Api-Key: your-api-key-here"
{
"visits": {
"data": [
{
"date": "2024-12-01T15:23:10Z",
"referer": "",
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)",
"visitLocation": {
"cityName": "Chicago",
"countryName": "United States",
"regionName": "Illinois"
}
}
],
"pagination": {
"currentPage": 1,
"pagesCount": 3,
"totalItems": 42
}
}
}
Base URL: http://10.0.0.250:9000/api
API Documentation: https://listmonk.app/docs/apis/apis
Description: Create or update a subscriber
{
"email": "user@example.com",
"name": "John Doe",
"status": "enabled",
"lists": [1],
"attribs": {
"city": "Chicago",
"qr_id": "T42",
"entry_month": "2024-12"
},
"preconfirm_subscriptions": false
}
curl -X POST "http://10.0.0.250:9000/api/subscribers" \
-u "admin:your-password" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"name": "John Doe",
"status": "enabled",
"lists": [1],
"preconfirm_subscriptions": false
}'
{
"data": {
"id": 123,
"created_at": "2024-12-01T10:30:00Z",
"updated_at": "2024-12-01T10:30:00Z",
"email": "user@example.com",
"name": "John Doe",
"status": "enabled",
"lists": [
{
"id": 1,
"name": "Mad Monkey - Benny Campaign",
"subscription_status": "unconfirmed"
}
]
}
}
preconfirm_subscriptions is false, Listmonk automatically sends a double opt-in email. Set to true to skip confirmation (not recommended for compliance).
Description: List subscribers with filters
| Parameter | Type | Description |
|---|---|---|
| query | string | SQL WHERE clause (e.g., "subscribers.email LIKE '%@gmail.com'") |
| list_id | integer | Filter by list ID |
| page | integer | Page number |
| per_page | integer | Items per page (max 100) |
curl -X GET "http://10.0.0.250:9000/api/subscribers?list_id=1&query=subscribers.attribs->>'entry_month'='2024-12'" \ -u "admin:your-password"
Description: Send a campaign (transactional email)
{
"status": "running"
}
curl -X PUT "http://10.0.0.250:9000/api/campaigns/5/status" \
-u "admin:your-password" \
-H "Content-Type: application/json" \
-d '{"status": "running"}'
Description: Send transactional email (for drip campaigns)
{
"subscriber_email": "user@example.com",
"template_id": 2,
"data": {
"name": "John",
"story": "Benny was spotted in Chicago, then traveled to Milwaukee...",
"discount_code": "BANANAS10"
}
}
curl -X POST "http://10.0.0.250:9000/api/tx" \
-u "admin:your-password" \
-H "Content-Type: application/json" \
-d '{
"subscriber_email": "user@example.com",
"template_id": 2,
"data": {
"name": "John",
"discount_code": "BANANAS10"
}
}'
Base URL: https://ipapi.co
Rate Limit: 1,000 requests/day (free tier), 30,000/month (paid)
curl "https://ipapi.co/203.0.113.42/json/"
{
"ip": "203.0.113.42",
"city": "Chicago",
"region": "Illinois",
"region_code": "IL",
"country": "US",
"country_name": "United States",
"postal": "60601",
"latitude": 41.8781,
"longitude": -87.6298,
"timezone": "America/Chicago",
"org": "Comcast Cable Communications LLC"
}
https://ipapi.co/{{ $json.ip }}/json/
Base URL: https://ipinfo.io
Rate Limit: 50,000 requests/month (free tier)
curl "https://ipinfo.io/203.0.113.42/json?token=YOUR_TOKEN"
{
"ip": "203.0.113.42",
"city": "Chicago",
"region": "Illinois",
"country": "US",
"loc": "41.8781,-87.6298",
"postal": "60601",
"timezone": "America/Chicago",
"org": "AS7922 Comcast Cable Communications LLC"
}
Base URL: https://api.printify.com/v1
Documentation: https://developers.printify.com
Authorization: Bearer YOUR_TOKEN
{
"external_id": "prize-2024-12",
"label": "Mad Monkey Winner - December 2024",
"line_items": [
{
"product_id": "your-product-id",
"variant_id": 12345,
"quantity": 1
}
],
"shipping_method": 1,
"address_to": {
"first_name": "John",
"last_name": "Doe",
"email": "user@example.com",
"address1": "123 Main St",
"city": "Chicago",
"region": "IL",
"zip": "60601",
"country": "US"
}
}
curl -X POST "https://api.printify.com/v1/shops/YOUR_SHOP_ID/orders.json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d @order.json
Base URL: https://openapi.etsy.com/v3
Documentation: https://developers.etsy.com
x-api-key header
curl "https://openapi.etsy.com/v3/application/shops/YOUR_SHOP_ID/listings/active" \ -H "x-api-key: YOUR_API_KEY"