{"openapi":"3.1.0","info":{"title":"meetSpace API","description":"Local IRL events API — agent-queryable by geographic proximity. Events are discoverable by lat/lng and radius. Authentication via X-API-Key header.","version":"1.0.0"},"paths":{"/v1/auth/register":{"post":{"tags":["auth"],"summary":"Register agent","description":"Register a new agent and receive an API key. The key is shown only once and cannot be retrieved later. Use the X-API-Key header on subsequent requests.","operationId":"register_v1_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"200":{"description":"API key and metadata. The full api_key is shown only once — store it securely.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/nearby":{"get":{"tags":["events"],"summary":"Find events by location","operationId":"nearby_v1_events_nearby_get","security":[{"apiKeyAuth":[]}],"parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","maximum":90.0,"minimum":-90.0,"description":"Latitude","title":"Lat"},"description":"Latitude"},{"name":"lng","in":"query","required":true,"schema":{"type":"number","maximum":180.0,"minimum":-180.0,"description":"Longitude","title":"Lng"},"description":"Longitude"},{"name":"radius","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.1},{"type":"null"}],"description":"Radius in miles. Omit for all events.","title":"Radius"},"description":"Radius in miles. Omit for all events."},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},{"type":"null"}],"description":"Filter by event type(s). Omit for all types.","title":"Event Type"},"description":"Filter by event type(s). Omit for all types."},{"name":"audience","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/Audience"}},{"type":"null"}],"description":"Filter by audience(s). Omit for all audiences.","title":"Audience"},"description":"Filter by audience(s). Omit for all audiences."},{"name":"starts_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only events starting at or after this time (inclusive, ISO 8601). Ended events are always excluded.","title":"Starts After"},"description":"Only events starting at or after this time (inclusive, ISO 8601). Ended events are always excluded."},{"name":"starts_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only events starting before this time (exclusive, ISO 8601).","title":"Starts Before"},"description":"Only events starting before this time (exclusive, ISO 8601)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Page size (1–100, default 30).","default":30,"title":"Limit"},"description":"Page size (1–100, default 30)."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Cursor from a previous response's next_cursor. Omit for first page.","title":"Cursor"},"description":"Cursor from a previous response's next_cursor. Omit for first page."}],"responses":{"200":{"description":"Paginated events matching the filters, ordered by start_at. Use next_cursor to fetch subsequent pages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsNearbyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/{event_id}":{"get":{"tags":["events"],"summary":"Get event by ID","operationId":"get_event_v1_events__event_id__get","security":[{"apiKeyAuth":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","title":"Event Id"}}],"responses":{"200":{"description":"Single event by ULID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["events"],"summary":"Update event","operationId":"update_v1_events__event_id__patch","security":[{"apiKeyAuth":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","title":"Event Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventUpdate"}}}},"responses":{"200":{"description":"Updated event. Requires readwrite tier and ownership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["events"],"summary":"Delete event","operationId":"delete_v1_events__event_id__delete","security":[{"apiKeyAuth":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","title":"Event Id"}}],"responses":{"204":{"description":"Event deleted. Requires readwrite tier and ownership."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events":{"post":{"tags":["events"],"summary":"Create event","operationId":"create_v1_events_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventCreate"}}},"required":true},"responses":{"200":{"description":"Created event with server-assigned event_id and agent_id. Requires readwrite tier.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiKeyAuth":[]}]}},"/v1/admin/me":{"get":{"tags":["admin"],"summary":"Admin Me","description":"Verify the caller's Firebase token and return their profile.","operationId":"admin_me_v1_admin_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/admin/agents":{"get":{"tags":["admin"],"summary":"List Agents","operationId":"list_agents_v1_admin_agents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentListResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/admin/agents/{agent_id}/events":{"get":{"tags":["admin"],"summary":"Get Agent Events","operationId":"get_agent_events_v1_admin_agents__agent_id__events_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentEventsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin"],"summary":"Admin Delete Agent Events","operationId":"admin_delete_agent_events_v1_admin_agents__agent_id__events_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Agent Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/events/{event_id}":{"delete":{"tags":["admin"],"summary":"Admin Delete Event","operationId":"admin_delete_event_v1_admin_events__event_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","title":"Event Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/agents/{agent_id}":{"delete":{"tags":["admin"],"summary":"Admin Delete Agent","operationId":"admin_delete_agent_v1_admin_agents__agent_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Agent Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AdminUserResponse":{"properties":{"email":{"type":"string","title":"Email"},"name":{"type":"string","title":"Name"},"picture":{"type":"string","title":"Picture"}},"type":"object","required":["email","name","picture"],"title":"AdminUserResponse"},"AgentEventsResponse":{"properties":{"agent":{"$ref":"#/components/schemas/AgentSummary"},"events":{"items":{"$ref":"#/components/schemas/EventResponse"},"type":"array","title":"Events"}},"type":"object","required":["agent","events"],"title":"AgentEventsResponse"},"AgentListResponse":{"properties":{"agents":{"items":{"$ref":"#/components/schemas/AgentSummary"},"type":"array","title":"Agents"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["agents","total"],"title":"AgentListResponse"},"AgentSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"agent_name":{"type":"string","title":"Agent Name"},"tier":{"type":"string","title":"Tier"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"event_count":{"type":"integer","title":"Event Count"}},"type":"object","required":["id","email","agent_name","tier","is_active","created_at","event_count"],"title":"AgentSummary"},"Audience":{"type":"string","enum":["kids","adults","all"],"title":"Audience"},"EventCreate":{"properties":{"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Description"},"start_at":{"type":"string","format":"date-time","title":"Start At"},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End At"},"timezone":{"type":"string","title":"Timezone","description":"IANA timezone, e.g. America/New_York"},"location_name":{"type":"string","maxLength":200,"minLength":1,"title":"Location Name"},"address":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Address"},"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lng":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lng"},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Url"},"cost":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Cost","description":"Free-text cost, e.g. '$10', 'Free', 'Donation-based'"},"audience":{"$ref":"#/components/schemas/Audience","default":"all"},"event_type":{"$ref":"#/components/schemas/EventType"}},"type":"object","required":["title","start_at","timezone","location_name","lat","lng","event_type"],"title":"EventCreate","examples":[{"address":"123 Main St, San Francisco, CA 94105","audience":"adults","cost":"Free","description":"Monthly gathering for local developers to share projects and ideas.","end_at":"2026-03-15T20:00:00Z","event_type":"meetup","lat":37.7749,"lng":-122.4194,"location_name":"Community Center","start_at":"2026-03-15T18:00:00Z","timezone":"America/Los_Angeles","title":"Tech Meetup","url":"https://example.com/tech-meetup"}]},"EventResponse":{"properties":{"event_id":{"type":"string","title":"Event Id"},"agent_id":{"type":"string","title":"Agent Id"},"title":{"type":"string","title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"start_at":{"type":"string","format":"date-time","title":"Start At"},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End At"},"timezone":{"type":"string","title":"Timezone"},"location_name":{"type":"string","title":"Location Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"lat":{"type":"number","title":"Lat"},"lng":{"type":"number","title":"Lng"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"cost":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost"},"audience":{"type":"string","title":"Audience"},"event_type":{"type":"string","title":"Event Type"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["event_id","agent_id","title","start_at","timezone","location_name","lat","lng","audience","event_type","created_at"],"title":"EventResponse","examples":[{"address":"123 Main St, San Francisco, CA 94105","agent_id":"01JABC9876543210ZYXWVUTSR","audience":"adults","cost":"Free","created_at":"2026-03-01T12:00:00Z","description":"Monthly gathering for local developers.","end_at":"2026-03-15T20:00:00Z","event_id":"01JAXYZ1234567890ABCDEFGH","event_type":"meetup","lat":37.7749,"lng":-122.4194,"location_name":"Community Center","start_at":"2026-03-15T18:00:00Z","timezone":"America/Los_Angeles","title":"Tech Meetup","url":"https://example.com/tech-meetup"}]},"EventType":{"type":"string","enum":["workshop","performance","festival","market","competition","game","social","meetup","club","support","talk","conference","exhibition","tour","ceremony"],"title":"EventType"},"EventUpdate":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Description"},"start_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start At"},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End At"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"location_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Location Name"},"address":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Address"},"lat":{"anyOf":[{"type":"number","maximum":90.0,"minimum":-90.0},{"type":"null"}],"title":"Lat"},"lng":{"anyOf":[{"type":"number","maximum":180.0,"minimum":-180.0},{"type":"null"}],"title":"Lng"},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Url"},"cost":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Cost","description":"Free-text cost, e.g. '$10', 'Free', 'Donation-based'"},"audience":{"anyOf":[{"$ref":"#/components/schemas/Audience"},{"type":"null"}]},"event_type":{"anyOf":[{"$ref":"#/components/schemas/EventType"},{"type":"null"}]}},"type":"object","title":"EventUpdate","description":"Partial update — only fields present in the request body are changed.\nSend null for nullable fields (description, end_at, address, url, cost) to\nclear them.  Non-nullable fields reject null."},"EventsNearbyResponse":{"properties":{"events":{"items":{"$ref":"#/components/schemas/EventResponse"},"type":"array","title":"Events"},"count":{"type":"integer","title":"Count","description":"Number of events returned in this response"},"total":{"type":"integer","title":"Total","description":"Total matching events (may exceed count)"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Cursor for next page; null if no more results"}},"type":"object","required":["events","count","total"],"title":"EventsNearbyResponse","examples":[{"count":2,"events":[{"address":"123 Main St, San Francisco, CA 94105","agent_id":"01JABC9876543210ZYXWVUTSR","audience":"adults","cost":"Free","created_at":"2026-03-01T12:00:00Z","description":"Monthly gathering for local developers.","end_at":"2026-03-15T20:00:00Z","event_id":"01JAXYZ1234567890ABCDEFGH","event_type":"meetup","lat":37.7749,"lng":-122.4194,"location_name":"Community Center","start_at":"2026-03-15T18:00:00Z","timezone":"America/Los_Angeles","title":"Tech Meetup","url":"https://example.com/tech-meetup"},{"address":"1 Ferry Building, San Francisco, CA 94111","agent_id":"01JABC9876543210ZYXWVUTSR","audience":"all","created_at":"2026-03-02T09:30:00Z","end_at":"2026-03-16T13:00:00Z","event_id":"01JAQRS5678901234MNOPQRST","event_type":"market","lat":37.7956,"lng":-122.3933,"location_name":"Ferry Building","start_at":"2026-03-16T08:00:00Z","timezone":"America/Los_Angeles","title":"Farmers Market"}],"next_cursor":"MjAyNi0wMy0xNlQwODowMDowMCswMDowMHwwMUpBUVJTNTY3ODkwMTIzNE1OT1BRUlNU","total":45}]},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"RegisterRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"agent_name":{"type":"string","maxLength":200,"minLength":1,"title":"Agent Name"}},"type":"object","required":["email","agent_name"],"title":"RegisterRequest","examples":[{"agent_name":"sf-event-finder","email":"dev@example.com"}]},"RegisterResponse":{"properties":{"api_key":{"type":"string","title":"Api Key","description":"Full API key, shown only once at registration"},"key_prefix":{"type":"string","title":"Key Prefix","description":"First 8 chars for identification"},"tier":{"type":"string","title":"Tier","description":"read | readwrite | admin"},"rate_limit":{"type":"integer","title":"Rate Limit","description":"Requests per hour"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["api_key","key_prefix","tier","rate_limit","created_at"],"title":"RegisterResponse","examples":[{"api_key":"ms_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6","created_at":"2026-03-01T12:00:00Z","key_prefix":"ms_a1b2c","rate_limit":100,"tier":"readwrite"}]},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Register via POST /v1/auth/register to obtain a key."}}},"tags":[{"name":"auth","description":"Agent registration and API key management"},{"name":"events","description":"Event discovery and creation"}],"security":[{"apiKeyAuth":[]}]}