# trellis

> a clean read-only api for the public web's loud corners

read-only json for reddit, 4chan, x and web search. no auth, no keys, no accounts.
it's a pass-through with a short cache, so it is only as up as the sites behind it.

## endpoints

- `GET https://trellis.bada.im/reddit/r/{sub}/{hot|new|top|rising|controversial}.json` (limit=1..100, after={cursor}): subreddit listing, list of post
- `GET https://trellis.bada.im/reddit/comments/{id}.json` (limit=1..100, sort=best|top|new|controversial|old|qa): a post and its comments, flattened depth-first
- `GET https://trellis.bada.im/reddit/r/{sub}/{hot|new|top|rising|controversial}.json` (t=hour|day|week|month|year|all): listing with time window (top/controversial)
- `GET https://trellis.bada.im/reddit/search.json` (q (required), limit=1..100, after={cursor}): reddit search, list of post
- `GET https://trellis.bada.im/reddit/r/{sub}/search.json` (q (required), restrict_sr=1, sort, t, limit, after): search within one subreddit
- `GET https://trellis.bada.im/reddit/subreddits/search.json` (q (required), limit=1..100): find subreddits by name/topic, list of subreddit
- `GET https://trellis.bada.im/reddit/r/{sub}/about.json`: one subreddit's about (a single item)
- `GET https://trellis.bada.im/reddit/multi/{subs}.json` (sort, t, limit, after (subs joined by +)): combined listing across several subreddits
- `GET https://trellis.bada.im/reddit/morechildren.json` (link_id (required), children (required, comma ids), sort): expand collapsed comment stubs
- `GET https://trellis.bada.im/chan/{board}/catalog.json`: every thread on a 4chan board, list of thread
- `GET https://trellis.bada.im/chan/{board}/thread/{no}.json`: a 4chan thread: op (thread) then replies (post)
- `GET https://trellis.bada.im/x/status/{id}.json`: one tweet, a single item (not a list)
- `GET https://trellis.bada.im/g/search.json` (q (required), limit=1..100): web search results, list of serp

all GET. `limit` outside 1..100 is a 400, not a clamp.
send `Accept: text/markdown` to get the same data as markdown instead of json.

## envelope (trellis.v1)

every item has the same keys:

```json
{"schema":"trellis.v1","source":"reddit|4chan|x|google","kind":"post|comment|thread|tweet|serp|subreddit",
 "id":"","url":"","parent_id":null,"thread_id":null,"author":null,"created_at":null,
 "title":null,"body_md":"","media":[],"metrics":{},"rank":null,
 "fetched_at":"ISO8601","tier":"","provenance":{"cache":"hit|miss","upstream_url":""}}
```

lists are `{"schema":"trellis.v1","source":"","items":[],"after":null,"count":N}`.
pass `after` back as `?after=` to get the next page (reddit only).

- `body_md`: text with html stripped, `<br>` as newlines, links reduced to their text.
- `null` means the upstream didn't say. we don't fill gaps with guesses.
- `tier`: which upstream answered. reddit `api` or `json`; 4chan `api`; x `syndication` or `oembed`; search `searxng`.
- `provenance.cache`: `hit` if this came from our cache.
- search items also carry `provenance.engines`, the search engines that returned that result.
  google is asked first, but when it refuses us the results come from the others. `source` stays `google`.

## errors

`{"schema":"trellis.v1","error":"..."}` with 400 (bad input), 404 (no such thing upstream),
502 (upstream refused or broke; `upstream_status` says how).

## limits

cache: listings 60s, threads 300s, tweets 3600s, search 300s. 4chan is fetched at most once a second,
so a cold 4chan request can wait a moment. please don't hammer it; it runs on one box.

## more

- meta: https://trellis.bada.im/_meta
- agent card: https://trellis.bada.im/.well-known/agent.json
- crawler: https://trellis.bada.im/bot
