API reference

Four endpoints: a page of events, one event, and the two vocabularies needed to query them. Every one is a GET, every one needs the events:read scope, and every one is relative to https://api.locally-social.com/api/v1.

List events

GET/events

Upcoming public events, soonest first. Cursor-paged. Only events at a visible venue with a public page are returned, so the count here will not match a raw corpus total.

Location

Three ways to say where, and the city composes with either of the others as an AND. The ZIP and the coordinate pair are both centres, so naming both is a 422.

citystring
City name or slug — Charlotte or charlotte. Must be sent with state; one without the other is a 422 rather than a half-applied filter.
statestring
Two-letter state code. Must be sent with city.
zipcodestring
Five digits. Resolves to the ZIP’s centroid and searches radius_miles around it — so this means “near this ZIP”, not “in it”, and will include a venue three blocks over the line. Not combinable with lat/lng. A well-formed ZIP loso holds no centroid for is a 422.
latnumber
−90 to 90. Send with lng.
lngnumber
−180 to 180. Send with lat.
radius_milesnumber
Applies to zipcode and to lat/lng. Defaults to 15, caps at 100. Ignored when the only location is city/state, which is an administrative boundary rather than a centre.

Time and category

starts_aftertimestamp
ISO 8601. Defaults to now — the API is forward-looking, and a default that included last year would make the first call useless. Pass an explicit past instant to read history.
starts_beforetimestamp
ISO 8601. Exclusive upper bound on start time.
updated_sincetimestamp
ISO 8601. Only events whose row changed at or after this instant. A filter, not a change feed: it cannot tell you an event was deleted or stopped being public, and a row that changes while you are paging may be missed. Re-read a window you care about rather than relying on this to be exhaustive.
categorystring
A name or a slug from /categories — both are accepted. An unknown value is a 422 naming the mistake, not a 200 with an empty page.

Paging

limitinteger
Rows per page. Defaults to 25, capped by tier (25 / 50 / 200). A larger value is clamped, not refused — asking for more than a tier gives still answers, with a cursor to continue.
cursorstring
The next_cursor from a previous response, unchanged. Opaque: its contents will change, so parsing it is the one way to be broken by a release that kept every compatibility promise. A cursor loso did not issue is a 422.
curl "https://api.locally-social.com/api/v1/events?city=Charlotte&state=NC&category=comedy&limit=50" \
  -H "Authorization: Bearer $LOSO_API_KEY"
200 application/json
{
  "data": [
    {
      "id": "9f1c6b4e-2a71-4d58-9c33-0e5a7b812d04",
      "title": "Thursday Night Trivia",
      "description": "Six rounds, teams of up to six, no phones.",
      "start_at": "2026-11-05T23:30:00Z",
      "end_at": null,
      "time_tbd": false,
      "categories": ["Trivia & Games"],
      "is_recurring": true,
      "recurrence_pattern": "Weekly on Thursday",
      "price": 0,
      "ticket_url": null,
      "image_url": "https://cdn.locally-social.com/events/9f1c6b4e.jpg",
      "is_sold_out": false,
      "url": "https://locally-social.com/events/charlotte-nc/thursday-night-trivia-9f1c6b4e2a71",
      "updated_at": "2026-11-01T14:02:11Z",
      "venue": {
        "id": "c4e81a92-7f30-4b6d-85a1-2d9e03f7b418",
        "name": "Selwyn Avenue Taproom",
        "address": "2801 Selwyn Ave",
        "city": "Charlotte",
        "state": "NC",
        "neighborhood": "Myers Park",
        "latitude": 35.1823,
        "longitude": -80.8471
      }
    }
  ],
  "next_cursor": "MjAyNi0xMS0wNVQyMzozMDowMCswMDowMHw5ZjFjNmI0ZQ"
}

There is no total. Counting the match set costs a second scan on every page and a cursor API does not need one — page until next_cursor comes back null. A count that is only approximately right is worse than none.

Retrieve an event

GET/events/{event_id}

One event by id, including one that has already happened — an id from last week reads “this happened” rather than a 404 that cannot be told apart from an event loso never had.

event_iduuidrequired
Path parameter. The id from any listing response.
curl "https://api.locally-social.com/api/v1/events/9f1c6b4e-2a71-4d58-9c33-0e5a7b812d04" \
  -H "Authorization: Bearer $LOSO_API_KEY"
200 application/json
{
  "id": "9f1c6b4e-2a71-4d58-9c33-0e5a7b812d04",
  "title": "Thursday Night Trivia",
  "description": "Six rounds, teams of up to six, no phones.",
  "start_at": "2026-11-05T23:30:00Z",
  "end_at": null,
  "time_tbd": false,
  "categories": ["Trivia & Games"],
  "is_recurring": true,
  "recurrence_pattern": "Weekly on Thursday",
  "price": 0,
  "ticket_url": null,
  "image_url": "https://cdn.locally-social.com/events/9f1c6b4e.jpg",
  "is_sold_out": false,
  "url": "https://locally-social.com/events/charlotte-nc/thursday-night-trivia-9f1c6b4e2a71",
  "updated_at": "2026-11-01T14:02:11Z",
  "venue": {
    "id": "c4e81a92-7f30-4b6d-85a1-2d9e03f7b418",
    "name": "Selwyn Avenue Taproom",
    "address": "2801 Selwyn Ave",
    "city": "Charlotte",
    "state": "NC",
    "neighborhood": "Myers Park",
    "latitude": 35.1823,
    "longitude": -80.8471
  }
}

List categories

GET/categories

Every value the category filter accepts, with a count of upcoming events behind each. A category with nothing behind it is listed at zero rather than omitted, so this is a stable vocabulary to build a filter UI from.

Not paged, and not fenced on a trial key: the counts cover the full corpus on every tier, so the vocabulary tells you what live access covers before you have it.

curl "https://api.locally-social.com/api/v1/categories" \
  -H "Authorization: Bearer $LOSO_API_KEY"
200 application/json
[
  { "name": "Arts & Culture", "slug": "arts-culture", "upcoming_event_count": 48 },
  { "name": "Beer / Brewery", "slug": "beer-brewery", "upcoming_event_count": 112 },
  { "name": "Comedy", "slug": "comedy", "upcoming_event_count": 31 },
  { "name": "Trivia & Games", "slug": "trivia-games", "upcoming_event_count": 96 }
]
namestring
The value that appears in an event’s categories array. Accepted by ?category=.
slugstring
URL-safe form, also accepted by ?category=.
upcoming_event_countinteger
Events upcoming in this category, corpus-wide.

List cities

GET/cities

Cities with upcoming coverage, deepest first. This is the honest answer to “where does loso have data” — and the right place to look before sending a city/state pair.

Not paged, and not fenced on a trial key.

curl "https://api.locally-social.com/api/v1/cities" \
  -H "Authorization: Bearer $LOSO_API_KEY"
200 application/json
[
  { "city": "Charlotte", "state": "NC", "upcoming_event_count": 1842 },
  { "city": "Raleigh", "state": "NC", "upcoming_event_count": 503 }
]

The event object

Every field an event carries. A field may be added in a future release; none is renamed, removed or re-typed within v1.

iduuid
Stable. Never reused.
titlestring
Never null.
descriptionstring | null
Null where the source published none. Length is not bounded.
start_attimestamp
UTC, always. Local time is the venue’s — use venue to work out where that is. Never null.
end_attimestamp | null
Null when the organiser did not state one, which is most events. Not a duration of zero — rendering it as an end time equal to the start is the common mistake here.
time_tbdboolean
True when only the date is known. start_at then carries a placeholder time that must not be displayed as the start. Check this before formatting a clock time.
categoriesstring[]
Values from /categories. Empty when unclassified — not null.
is_recurringboolean
Whether this event is one occurrence of a repeating series.
recurrence_patternstring | null
Human-readable, e.g. Weekly on Thursday. For display, not for parsing — it is not an RRULE and its wording is not part of the contract.
pricenumber | null
USD. Three states, not interchangeable: a number is the price, 0 means free, and null means no price was published — which is not the same as free and must not be rendered as it.
ticket_urlstring | null
Where to buy, when the source published a link. Points off-site as often as not.
image_urlstring | null
Cover art. Null is common.
is_sold_outboolean
Whether the source reports no remaining tickets.
urlstring
The event’s page on locally-social.com. Never null — an event with no page is excluded from the listing rather than served with a URL that would 404.
updated_attimestamp
When the row last changed. Usable with updated_since to skip events you already hold.
venueobject | null
Where it happens, nested rather than referenced — see below. Null only when loso has neither a venue row nor a name.

The venue object

Nested inside the event, never fetched separately. A caller rendering a listing needs the venue name and coordinates on every row, and one request per venue would turn one page into fifty calls against a per-minute limit. There is no venue collection.

iduuid | null
Null for a venue loso knows only as a name — a flyer that says “The Backroom” and nothing more. The name is still returned; there is simply no venue resource behind it. Handle this: it is common, and it is the case a happy-path sample will not show you.
namestring | null
The venue's name, or the name off the flyer.
addressstring | null
Short form, e.g. `2801 Selwyn Ave`.
citystring | null
Parsed from the address.
statestring | null
Two-letter code.
neighborhoodstring | null
Where loso has one. Often null outside Charlotte.
latitudenumber | null
Null together with `longitude` for an unlocated venue.
longitudenumber | null
See `latitude`.
An event whose venue is only a name
{
  "id": "1b7f20c8-5d49-4e02-a6f1-8c3b5e7d9011",
  "title": "Backlot Night Market",
  "start_at": "2026-11-08T21:00:00Z",
  "end_at": null,
  "time_tbd": false,
  "categories": ["Markets & Shopping"],
  "is_recurring": false,
  "recurrence_pattern": null,
  "price": null,
  "ticket_url": null,
  "image_url": null,
  "is_sold_out": false,
  "url": "https://locally-social.com/events/charlotte-nc/backlot-night-market-1b7f20c85d49",
  "updated_at": "2026-11-02T09:41:55Z",
  "venue": {
    "id": null,
    "name": "The Backlot",
    "address": null,
    "city": null,
    "state": null,
    "neighborhood": null,
    "latitude": null,
    "longitude": null
  }
}

Google-derived venue attributes — rating, review count, price level, business status, photos, the Places type taxonomy — are deliberately absent, as is the URL loso crawled an event from.

API reference · loso API