{"openapi":"3.1.0","info":{"title":"Afootly API","version":"1.0.0","description":"Read the same structured records the website renders. Reads are free; send X-Api-Key for metered access. Writes require a key with the 'write' scope and enter the moderation queue.","contact":{"email":"hello@afootly.com"},"license":{"name":"CC BY 4.0 (own data); source licences apply to ingested data"}},"servers":[{"url":"https://afootly.com/api/v1"}],"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"X-Api-Key"}},"schemas":{"Area":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"name_cy":{"type":["string","null"]},"level":{"type":"string","enum":["region","town","village"]},"parent_slug":{"type":["string","null"]},"lat":{"type":"number"},"lng":{"type":"number"},"boundary":{"type":"object","description":"GeoJSON Polygon"},"councils":{"type":"array","items":{"type":"string"}},"url":{"type":"string"}}},"Category":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"axis":{"type":"string","enum":["service","place","capability"]}}},"OpeningHours":{"type":"object","description":"Keys mo..su; each an array of [open, close] pairs in HH:MM; empty array = closed","additionalProperties":{"type":"array","items":{"type":"array","items":{"type":"string"},"minItems":2,"maxItems":2}}},"Business":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"category":{"$ref":"#/components/schemas/Category"},"capabilities":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"also_does":{"type":"array","items":{"$ref":"#/components/schemas/Category"},"description":"Other categories this business also covers; it appears under each of their filters"},"description":{"type":["string","null"]},"address":{"type":["string","null"]},"postcode":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"phone":{"type":["string","null"]},"phone_tel":{"type":["string","null"]},"email":{"type":["string","null"]},"website":{"type":["string","null"]},"opening_hours":{"$ref":"#/components/schemas/OpeningHours"},"fsa_rating":{"type":["string","null"]},"primary_area":{"type":"string"},"areas":{"type":"array","items":{"type":"string"}},"claimed":{"type":"boolean"},"source":{"type":"string"},"url":{"type":"string"},"reviews":{"$ref":"#/components/schemas/ReviewSummary"},"updated_at":{"type":"string","format":"date-time"}}},"ReviewSummary":{"type":"object","properties":{"verified_count":{"type":"integer"},"unverified_count":{"type":"integer"},"score":{"type":["integer","null"],"description":"0–100 composite from verified reviews only"},"questions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["yesno","scale5"]},"value":{"type":["number","null"]},"n":{"type":"integer"}}}}}},"Event":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":["string","null"],"format":"date-time"},"venue":{"type":["object","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"category":{"type":"string"},"age_min":{"type":["integer","null"]},"age_max":{"type":["integer","null"]},"indoor_outdoor":{"type":["string","null"],"enum":["indoor","outdoor","both",null]},"cost_band":{"type":["string","null"]},"booking_required":{"type":"boolean"},"booking_url":{"type":["string","null"]},"in_catchment":{"type":"boolean","description":"Inside the area's own catchment, rather than nearby"},"distance_km":{"type":["number","null"]},"location_precision":{"type":["string","null"],"enum":["venue","postcode","town",null]},"url":{"type":"string"}}},"EventInput":{"type":"object","required":["title","starts_at","submitter_email"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time"},"venue_name":{"type":"string"},"category":{"type":"string"},"age_min":{"type":"integer"},"age_max":{"type":"integer"},"indoor_outdoor":{"type":"string","enum":["indoor","outdoor","both"]},"cost_band":{"type":"string","enum":["free","under_5","5_to_15","15_to_40","over_40"]},"booking_required":{"type":"boolean"},"booking_url":{"type":"string"},"organiser_name":{"type":"string"},"submitter_email":{"type":"string","format":"email"}}},"Planning":{"type":"object","properties":{"ref":{"type":"string"},"council":{"type":"string"},"council_ref":{"type":"string"},"description":{"type":"string"},"address":{"type":["string","null"]},"postcode":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"type":{"type":["string","null"]},"state":{"type":["string","null"]},"agent":{"type":["string","null"]},"received_date":{"type":["string","null"],"format":"date"},"decided_date":{"type":["string","null"],"format":"date"},"decision":{"type":["string","null"]},"source_url":{"type":["string","null"]},"first_seen_at":{"type":"string","format":"date-time"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}},"paths":{"/areas":{"get":{"summary":"List live areas","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Area"}}}}}}}}}},"/areas/{slug}":{"get":{"summary":"Get an area","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/areas/{slug}/businesses":{"get":{"summary":"List businesses in an area","description":"Ordered by name, or by distance when lat/lng (or a category) is given. Never by payment.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"}},{"name":"lat","in":"query","schema":{"type":"number"}},{"name":"lng","in":"query","schema":{"type":"number"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"page_size","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Business"}},"meta":{"type":"object"}}}}}}}}},"/areas/{slug}/events":{"get":{"summary":"List upcoming events","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"age_min","in":"query","schema":{"type":"integer"}},{"name":"age_max","in":"query","schema":{"type":"integer"}},{"name":"indoor_outdoor","in":"query","schema":{"type":"string","enum":["indoor","outdoor","both"]}},{"name":"cost_band","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"within_km","in":"query","description":"Also include events this far from the area (default 24 km ≈ 15 miles; 0 = the area only). Events inside the area's catchment are always included.","schema":{"type":"number","minimum":0,"maximum":80}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"page_size","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}}}}}}},"post":{"summary":"Submit an event","description":"Enters the moderation queue, same as a human submission.","security":[{"ApiKey":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}},"responses":{"202":{"description":"Accepted"},"400":{"description":"Validation error"},"401":{"description":"Key required"}}}},"/areas/{slug}/planning":{"get":{"summary":"List planning applications","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"council","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"page_size","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Planning"}}}}}}}}}},"/areas/{slug}/capacity":{"get":{"summary":"Live spare capacity (cancellations, free slots)","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"},{"name":"kind","in":"query","schema":{"type":"string","enum":["trade_day","restaurant_table","appointment","event_ticket"]}}],"responses":{"200":{"description":"OK"}}}},"/areas/{slug}/deals":{"get":{"summary":"Live deals","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"}],"responses":{"200":{"description":"OK"}}}},"/areas/{slug}/data/{feed}":{"get":{"summary":"Live data feed","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Area slug, e.g. monmouth"},{"name":"feed","in":"path","required":true,"schema":{"type":"string","enum":["river","fuel","weather","power-cuts","crime"]}}],"responses":{"200":{"description":"OK"}}}},"/businesses/{slug}":{"get":{"summary":"Get a business with review summary","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Business"}}}}}},"404":{"description":"Not found"}}}},"/categories":{"get":{"summary":"Controlled vocabulary","parameters":[{"name":"axis","in":"query","schema":{"type":"string","enum":["service","place","capability"]}}],"responses":{"200":{"description":"OK"}}}},"/feeds":{"get":{"summary":"Ingestion status","responses":{"200":{"description":"OK"}}}}}}