{"components":{"responses":{"ClientError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Client error (invalid input, unauthorized, forbidden, not found or rate limited)"}},"schemas":{"Category":{"properties":{"id":{"example":1,"type":"integer"},"img_url":{"example":"group","type":"string"},"name":{"example":"Social & Meetups","type":"string"}},"type":"object"},"CollectionItem":{"properties":{"booklink":{"example":"https://padelfunchal.com/booking","nullable":true,"type":"string"},"can_view_details":{"example":true,"type":"boolean"},"category":{"$ref":"#/components/schemas/Category"},"creator_id":{"example":1,"type":"integer"},"id":{"example":280,"type":"integer"},"img_url":{"example":"/uploads/event/event_280/0_banner.webp","type":"string"},"is_locked":{"example":false,"type":"boolean"},"is_private":{"example":false,"type":"boolean"},"lat":{"example":32.6511,"format":"float","nullable":true,"type":"number"},"link":{"example":"/event/quinta-do-padel-funchal","type":"string"},"lng":{"example":-16.9088,"format":"float","nullable":true,"type":"number"},"location":{"example":"Funchal, Madeira","type":"string"},"min_user_type":{"enum":["free","plus","pro","adm"],"example":"free","type":"string"},"note":{"example":"Best outdoor courts with ocean view","nullable":true,"type":"string"},"opening_hours":{"example":"08:00 \u2013 23:00","nullable":true,"type":"string"},"order":{"example":0,"type":"integer"},"setting":{"enum":["outdoor","indoor","both"],"example":"outdoor","type":"string"},"slug":{"example":"quinta-do-padel-funchal","type":"string"},"start_dt":{"nullable":true,"type":"string"},"title":{"example":"Quinta do Padel Funchal","type":"string"},"token":{"nullable":true,"type":"string"},"type":{"enum":["event","place","collection"],"example":"place","type":"string"}},"type":"object"},"Error":{"properties":{"error":{"example":"Not found","type":"string"},"message":{"nullable":true,"type":"string"}},"type":"object"},"Event":{"properties":{"booklink":{"description":"Direct external booking or reservation URL","example":"https://simplifica.madeira.gov.pt/infoProcess/32/inicio","nullable":true,"type":"string"},"can_view_details":{"description":"True if full location, timeslots, and descriptions are accessible","example":true,"type":"boolean"},"category":{"$ref":"#/components/schemas/Category"},"category_id":{"example":1,"type":"integer"},"collection_items":{"description":"List of spots included in this collection (populated when type == 'collection')","items":{"$ref":"#/components/schemas/CollectionItem"},"type":"array"},"collections":{"description":"Parent collections this spot belongs to, including sibling navigation links","items":{"$ref":"#/components/schemas/ParentCollection"},"type":"array"},"creator_id":{"example":1,"type":"integer"},"desc":{"example":"Casual get-together for digital nomads and remote workers.","type":"string"},"end_dt":{"example":"24.08.2026 21:00","nullable":true,"type":"string"},"end_dt_iso":{"example":"2026-08-24T21:00:00+03:00","nullable":true,"type":"string"},"id":{"example":1,"type":"integer"},"img":{"example":["/uploads/event/event_1/1_uuid.jpg"],"items":{"type":"string"},"type":"array"},"img_url":{"example":"/uploads/event/event_1/1_uuid.jpg","type":"string"},"is_locked":{"description":"True if the viewing user does not meet min_user_type requirements","example":false,"type":"boolean"},"is_private":{"description":"True if event is unlisted and requires private token to view","example":false,"type":"boolean"},"lat":{"example":41.8385,"format":"float","nullable":true,"type":"number"},"ljoin_dt":{"example":"24.08.2026 17:00","nullable":true,"type":"string"},"lng":{"example":23.4885,"format":"float","nullable":true,"type":"number"},"location":{"example":"Coworking Bansko Rooftop, Bansko, Bulgaria","type":"string"},"max_part":{"example":30,"type":"integer"},"min_part":{"example":0,"type":"integer"},"min_user_type":{"description":"Required membership tier for access","enum":["free","plus","pro","adm"],"example":"free","type":"string"},"opening_hours":{"example":"Mon\u2013Fri: 09:00 \u2013 18:00, Sat\u2013Sun: 10:00 \u2013 16:00","nullable":true,"type":"string"},"setting":{"enum":["outdoor","indoor","both"],"example":"both","type":"string"},"slug":{"example":"bansko-nomad-sunset-meetup","type":"string"},"start_dt":{"example":"24.08.2026 18:00","nullable":true,"type":"string"},"start_dt_iso":{"example":"2026-08-24T18:00:00+03:00","nullable":true,"type":"string"},"tag":{"example":"bansko, meetup, drinks, networking","type":"string"},"timeslots":{"description":"Raw timeslots string (usually omitted in favor of timeslots_data)","nullable":true,"type":"string"},"timeslots_api":{"description":"Timeslot sync provider (simplifica, playtomic, field_pt, matchpoint)","enum":["simplifica","playtomic","field_pt","matchpoint"],"example":"simplifica","nullable":true,"type":"string"},"timeslots_api_url":{"description":"Endpoint URL or comma-separated court IDs for live availability","example":"127,129,130","nullable":true,"type":"string"},"timeslots_data":{"description":"Structured real-time court availability data","nullable":true,"type":"object"},"timeslots_min_slots":{"description":"Minimum required consecutive slots","example":1,"type":"integer"},"title":{"example":"Bansko Nomad Sunset Meetup & Drinks","type":"string"},"token":{"description":"Private shareable token for direct access","example":"e429532c","nullable":true,"type":"string"},"type":{"description":"Entity type: event, place, or collection","enum":["event","place","collection"],"example":"event","type":"string"}},"type":"object"},"PaginatedEventsResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Event"},"type":"array"},"lat":{"example":0.0,"format":"float","type":"number"},"lng":{"example":0.0,"format":"float","type":"number"},"max":{"description":"Page batch size (default 12)","example":12,"type":"integer"},"offset":{"description":"Pagination offset","example":0,"type":"integer"},"size":{"description":"Number of records in current page","example":12,"type":"integer"},"total":{"description":"Total matching records in dataset","example":51,"type":"integer"}},"type":"object"},"ParentCollection":{"properties":{"current_index":{"example":1,"type":"integer"},"id":{"example":265,"type":"integer"},"img_url":{"example":"/uploads/event/event_265/0_padel.webp","type":"string"},"is_private":{"example":false,"type":"boolean"},"items_summary":{"description":"Ordered summary of sibling spots in collection","items":{"type":"object"},"type":"array"},"link":{"example":"/event/madeira-padel-courts","type":"string"},"next_item":{"description":"Next spot in collection for linear navigation","nullable":true,"type":"object"},"note":{"nullable":true,"type":"string"},"prev_item":{"description":"Previous spot in collection for linear navigation","nullable":true,"type":"object"},"slug":{"example":"madeira-padel-courts","type":"string"},"title":{"example":"Madeira Padel Courts Guide","type":"string"},"token":{"nullable":true,"type":"string"},"total_items":{"example":6,"type":"integer"}},"type":"object"},"User":{"properties":{"id":{"example":1,"type":"integer"},"img_url":{"example":"/uploads/user/user_1/1_uuid.jpg","type":"string"},"is_admin":{"example":true,"type":"boolean"},"name":{"example":"Rudel","type":"string"},"type":{"enum":["gen","free","plus","pro","adm"],"example":"adm","type":"string"}},"type":"object"}},"securitySchemes":{"ApiKeyAuth":{"description":"Alternative header: `X-API-Key: nm_...`","in":"header","name":"X-API-Key","type":"apiKey"},"BearerAuth":{"bearerFormat":"API Token (nm_...)","description":"NomadMap account token: `Authorization: Bearer nm_...`","scheme":"bearer","type":"http"}}},"externalDocs":{"description":"NomadMap MCP server for AI assistants (Claude, Cursor, ChatGPT)","url":"https://nomadmap.io/mcp"},"info":{"contact":{"email":"info@nomadmap.io","name":"NomadMap","url":"https://nomadmap.io"},"description":"Public REST API for discovering digital nomad events, meetups, places & venues (coworking, cafes, sports courts), curated guides/collections, cities and categories on NomadMap.\n\n### Access\n- **All read (GET) endpoints are public** and need no authentication.\n- User-scoped actions (favorites, RSVPs, saved events) require a NomadMap account token: `Authorization: Bearer <api_token>` or `X-API-Key: <api_token>`.\n- Private or member-tier content is returned as a sanitized preview (`is_locked: true`).\n\n### Conventions\n- **Entity types**: `event` (scheduled), `place` (venue with opening hours / bookable timeslots), `collection` (curated guide with ordered items).\n- **Dates**: `DD.MM.YYYY HH:mm` plus ISO 8601 fields (`start_dt_iso`, `end_dt_iso`).\n- **Pagination**: `{ size, total, offset, max, data }` envelopes (default `max: 12`).\n\n### AI assistants\nFor LLM agents, prefer the Model Context Protocol server at `https://nomadmap.io/mcp` (docs: https://nomadmap.io/mcp, security: https://nomadmap.io/mcp/security, index: https://nomadmap.io/llms.txt).\n\nContact: info@nomadmap.io","license":{"name":"Proprietary - NomadMap terms apply","url":"https://nomadmap.io/terms"},"termsOfService":"https://nomadmap.io/terms","title":"NomadMap Discovery & Events API","version":"1.2.0","x-logo":{"altText":"NomadMap","url":"https://nomadmap.io/logo-192.png"}},"openapi":"3.0.3","paths":{"/api/data/addfavorite":{"put":{"description":"Toggles favorite state for current user.","operationId":"putDataAddfavorite","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"integer"}},"type":"object"}}},"required":true},"responses":{"200":{"description":"Updated favorite status"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"summary":"Toggle event bookmark / favorite","tags":["User actions"]}},"/api/data/category":{"get":{"operationId":"getDataCategory","responses":{"200":{"description":"List of all categories"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[],"summary":"List categories","tags":["Discovery"]}},"/api/data/cities":{"get":{"description":"Returns distinct global nomad destinations aggregated with total event and place counts.","operationId":"getDataCities","parameters":[{"description":"Optional type filter","in":"query","name":"type","schema":{"enum":["event","place"],"type":"string"}}],"responses":{"200":{"description":"List of cities with eventCount and placeCount"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[],"summary":"List destination cities with event and place counts","tags":["Discovery"]}},"/api/data/collections":{"get":{"description":"List curated itineraries, neighborhood guides, and spot collections.","operationId":"getDataCollections","parameters":[{"in":"query","name":"search","schema":{"type":"string"}},{"in":"query","name":"loc","schema":{"type":"string"}},{"in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"in":"query","name":"max","schema":{"default":12,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEventsResponse"}}},"description":"Paginated envelope of collections"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[],"summary":"List curated nomad guides & collections","tags":["Collections"]}},"/api/data/event":{"get":{"description":"Public search and filtering with geo-bounding, category, setting, collection membership, and text search.","operationId":"getDataEvent","parameters":[{"description":"Text search across title, description, location, tag","in":"query","name":"search","schema":{"type":"string"}},{"description":"Category ID or comma-separated IDs","in":"query","name":"category","schema":{"type":"string"}},{"description":"Filter by venue environment","in":"query","name":"setting","schema":{"enum":["outdoor","indoor","both"],"type":"string"}},{"description":"Filter entries belonging to a specific collection ID (e.g. 265)","in":"query","name":"collection","schema":{"type":"integer"}},{"description":"Location keyword filter (e.g. 'Madeira', 'Bansko')","in":"query","name":"loc","schema":{"type":"string"}},{"description":"Target latitude for proximity radius","in":"query","name":"lat","schema":{"type":"number"}},{"description":"Target longitude for proximity radius","in":"query","name":"lng","schema":{"type":"number"}},{"description":"Distance radius in kilometers","in":"query","name":"dist","schema":{"default":1000,"type":"integer"}},{"description":"Filter by entity type ('event', 'place', 'collection' or legacy 1, 2, 3)","in":"query","name":"type","schema":{"enum":["event","place","collection"],"type":"string"}},{"in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"Batch size (defaults to 12)","in":"query","name":"max","schema":{"default":12,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEventsResponse"}}},"description":"Paginated envelope containing events list and total count"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[],"summary":"List & filter events, places and collections","tags":["Events"]}},"/api/data/event/join":{"get":{"description":"Returns list of upcoming events the authenticated user has RSVP'd to.","operationId":"getDataEventJoin","responses":{"200":{"description":"Array of joined events"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"summary":"List joined events for current user","tags":["Events"]}},"/api/data/event/resolve/{token}":{"get":{"description":"Lightweight lookup returning the canonical ID, slug, and privacy status (used for 301 canonical redirects).","operationId":"getDataEventResolveByToken","parameters":[{"description":"Event slug, ID, or private share token","in":"path","name":"token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"id":{"example":1,"type":"integer"},"is_private":{"example":false,"type":"boolean"},"slug":{"example":"bansko-nomad-sunset-meetup","type":"string"}},"type":"object"}}},"description":"Canonical slug resolution object"},"404":{"description":"Token not found"}},"security":[],"summary":"Resolve canonical event slug by token or identifier","tags":["Events"]}},"/api/data/event/saved":{"get":{"description":"Returns list of events favorited by authenticated user.","operationId":"getDataEventSaved","responses":{"200":{"description":"Array of favorited events"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"summary":"List saved / bookmarked events for current user","tags":["Events"]}},"/api/data/event/{id}":{"get":{"description":"Returns full event/place details including photos, location, opening hours, collection items, and sibling links. Accepts numeric ID, canonical URL slug, or private share token.","operationId":"getDataEventById","parameters":[{"description":"Numeric event ID, canonical slug (e.g. 'bansko-nomad-sunset-meetup'), or private share token","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}},"description":"Event object"},"403":{"description":"Private event requires creator login or token"},"404":{"description":"Event not found"}},"security":[],"summary":"Get event, place, or collection by ID, slug, or token","tags":["Events"]}},"/api/data/joinevent":{"put":{"description":"Toggles participation state for current user on an event.","operationId":"putDataJoinevent","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"integer"}},"type":"object"}}},"required":true},"responses":{"200":{"description":"Updated participation status and refreshed event object"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"summary":"Toggle event RSVP / join","tags":["User actions"]}},"/api/data/places":{"get":{"description":"Direct shortcut endpoint to list and filter physical venues, coworking spaces, cafes, and padel clubs.","operationId":"getDataPlaces","parameters":[{"description":"Text search across venue name, description, address","in":"query","name":"search","schema":{"type":"string"}},{"description":"City or destination filter (e.g. 'Lisbon', 'Bali')","in":"query","name":"loc","schema":{"type":"string"}},{"description":"Category ID or comma-separated IDs","in":"query","name":"category","schema":{"type":"string"}},{"in":"query","name":"setting","schema":{"enum":["outdoor","indoor","both"],"type":"string"}},{"in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"in":"query","name":"max","schema":{"default":12,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEventsResponse"}}},"description":"Paginated envelope of physical places"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[],"summary":"List & filter physical places, coworking & venues","tags":["Places"]}},"/api/data/user":{"get":{"description":"Public directory of user profiles (id, name, avatar, tier). E-mail addresses are never included for other users.","operationId":"getDataUser","parameters":[{"in":"query","name":"search","schema":{"type":"string"}},{"in":"query","name":"type","schema":{"enum":["gen","free","plus","pro","adm"],"type":"string"}},{"in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"in":"query","name":"max","schema":{"default":50,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/User"},"type":"array"}}},"description":"List of public user profiles"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[],"summary":"List nomad users","tags":["Users"]}},"/api/data/user/{id}":{"get":{"operationId":"getDataUserById","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User profile object (e-mail only visible to the owner or admins)"},"4XX":{"$ref":"#/components/responses/ClientError"}},"security":[],"summary":"Get user profile by ID","tags":["Users"]}}},"servers":[{"description":"Production","url":"https://nomadmap.io"}],"tags":[{"description":"Events, places and collections: search, details, private links","name":"Events"},{"description":"Venues, coworking spaces, cafes and sports courts","name":"Places"},{"description":"Curated nomad guides and itineraries","name":"Collections"},{"description":"Cities and categories","name":"Discovery"},{"description":"Public user profiles","name":"Users"},{"description":"Authenticated favorites and RSVPs","name":"User actions"}]}
