Skip to content

Find listings

Market overview with facets

Counts by category, weekday, time, price, age and organization over a whole filtered set.

This page is for anyone showing "the market near here": how many classes and events, on which days, at what times and prices, for which ages, run by whom. You can get those numbers without downloading the listings. Add facets= to a list request and the response carries counts over every listing that matches your filters, not just the page you asked for.

It also covers the other half of the same question: when a count looks smaller than you expected, the response tells you which filters produced it.

Two things to know first

Three filters narrow a list even when you do not send them:

FilterDefaultApplies to
from / tofrom is today in the metro; on events to is from + 30 daysevents; classes and camps default only from, so their window is open-ended
min_confidence0.7 (0.5 on places)events, classes, camps, places
audienceeverything except adultsevents, classes, camps, places

A request with none of them sent therefore sees one month of events and leaves out lower-confidence and adult-audience listings. That is the right default for a family product, but it is easy to forget when you compare a list against a market-wide total.

Every list response says what it used. meta.applied_filters holds the value in effect for each filter the endpoint applies, and meta.defaults_applied names the ones that came from a default rather than from you:

cURL
curl -sS -H "X-API-Key: $TAILEND_API_KEY" --get https://api.tailend.dev/v1/philadelphia/events \
  --data-urlencode "lat=39.9526" \
  --data-urlencode "lng=-75.1652" \
  --data-urlencode "radius_m=8000" \
  --data-urlencode "limit=1"
Response
{
  "meta": {
    "applied_filters": {
      "from": "2026-09-30",
      "to": "2026-10-30",
      "min_confidence": 0.7,
      "audience": ["not_adults"],
      "lat": 39.9526,
      "lng": -75.1652,
      "radius_m": 8000
    },
    "defaults_applied": ["from", "to", "min_confidence", "audience"]
  }
}

To widen the view, send the filter yourself: to=2027-09-29 for a year of events, min_confidence=0 for everything regardless of confidence, audience=all to include adult listings. The echo then shows your value and drops the name from defaults_applied. The echoed value is always one you can send back: audience=not_adults (the default) returns exactly the set you got without the parameter.

The same two fields appear on events, classes, camps, places, /search, /nearby and /around. Only filters that endpoint applies are listed, so a weekday sent to /camps does not appear: the endpoint ignored it.

Ask for the counts

facets takes any of category, weekday, time_block, price_band, age_band and organization, comma-separated. Add limit=0 when you only want the counts:

curl -sS -H "X-API-Key: $TAILEND_API_KEY" --get https://api.tailend.dev/v1/philadelphia/classes \
  --data-urlencode "lat=39.9526" \
  --data-urlencode "lng=-75.1652" \
  --data-urlencode "radius_m=8000" \
  --data-urlencode "facets=category,weekday,time_block,price_band,age_band,organization" \
  --data-urlencode "limit=0"
Response
{
  "data": [],
  "facets": {
    "total": 112,
    "is_complete": true,
    "category": [
      { "value": "arts_creative", "count": 38 },
      { "value": "sports_active_play", "count": 27 },
      { "value": "music_movement", "count": 19 },
      { "value": "unspecified", "count": 4 }
    ],
    "weekday": [
      { "value": "monday", "count": 31 },
      { "value": "tuesday", "count": 36 },
      { "value": "wednesday", "count": 29 },
      { "value": "thursday", "count": 33 },
      { "value": "friday", "count": 18 },
      { "value": "saturday", "count": 44 },
      { "value": "sunday", "count": 12 }
    ],
    "time_block": [
      { "value": "morning", "count": 41 },
      { "value": "afternoon", "count": 39 },
      { "value": "evening", "count": 28 },
      { "value": "unspecified", "count": 4 }
    ],
    "price_band": [
      { "value": "free", "count": 9 },
      { "value": "under_20", "count": 14 },
      { "value": "20_to_50", "count": 35 },
      { "value": "50_to_100", "count": 22 },
      { "value": "100_plus", "count": 17 },
      { "value": "unspecified", "count": 15 }
    ],
    "age_band": [
      { "value": "baby", "count": 14 },
      { "value": "toddler", "count": 33 },
      { "value": "young_kids", "count": 51 },
      { "value": "bigger_kids", "count": 39 },
      { "value": "unspecified", "count": 12 }
    ],
    "organization": {
      "distinct": 41,
      "top": [
        { "id": "c45b9b3a-45ab-4f9c-b2e2-986dcb921f25", "name": "Example Arts Center", "count": 9 }
      ],
      "other_count": 97,
      "unspecified_count": 6
    }
  },
  "meta": { "limit": 0, "count": 0, "has_more": false, "next_cursor": null }
}

(Numbers are illustrative.) Without limit=0 you get a normal page in data and the same facets beside it, both from one request.

How to read the counts

  • total is the number of listings that match your filters. It is the number you would reach by paging the list to the end.
  • A listing is counted in every bucket it belongs to. A class that meets Monday and Wednesday is in both; a listing with two categories is in both. So category, age_band and a class's weekday can add up to more than total. time_block and price_band put each listing in exactly one bucket.
  • unspecified counts listings that do not state that detail (no start time, no price, no age range). It appears only when it is above zero.
  • Buckets. weekday is the local day of an event, or each day a class meets. time_block is morning (before 12:00), afternoon (12:00 to before 17:00) or evening (17:00 on), from the local start time. price_band is free for exactly the listings free=true returns, so the bucket and the filter give the same number; every other listing is banded by its lowest stated price in US dollars: under_20, 20_to_50, 50_to_100, 100_plus. A listing that is not free and states no price above zero is unspecified. age_band uses the same bands as ages.bands on a listing.
  • organization lists the twenty organizations with the most listings. other_count covers the rest, and unspecified_count the listings with no organization.
  • Not every facet exists on every collection. weekday is for events and classes; time_block and price_band are for events, classes and camps. Ask for one a collection has no data for and it is named in facets.unavailable instead of returning an empty list.

Facets answer the filters you send, so a market overview near a point is the same request you would page, with facets= and limit=0 added. Use the counts to draw the overview, then fetch a page only for the bucket the person opens.

Limits

  • facets= is available on every plan and counts as one request, however many listings it covers. A facets-only request returns no records.
  • page and cursor do not change the counts.
  • The organizations list is capped at twenty.
  • Very large sets are counted up to a fixed bound. When a count covers only part of the set, or counting ran out of time, facets.is_complete is false. Narrow the filters (a metro-wide overview is comfortably inside the bound) and ask again.
  • limit=0 is accepted only together with facets; on its own it is 400.
  • /search does not take facets.