# Shaping responses

> Trim or extend what comes back with fields=, expand= and include=.

Source: https://api.tailend.dev/docs/shaping-responses

The default response for every event, class, camp and place is lean. Four
parameters change what comes back:

```bash
curl -H "X-API-Key: $TAILEND_API_KEY" --get https://api.tailend.dev/v1/philadelphia/events \
  --data-urlencode "fields=name,place.name,price.is_free" \
  --data-urlencode "expand=place" \
  --data-urlencode "include=source" \
  --data-urlencode "include_mode=lenient"
```

| Parameter | What it does |
| --- | --- |
| `fields=` | Comma list of dotted paths to keep (`name,place.name`). `id` and `type` are always kept. |
| `expand=place,organization` | Attaches the full `Place`/`Organization` object under `expanded`, instead of just the reference. |
| `include=source` | A paid add-on. Attaches `source: {url, crawled_at, verification}` to each item. Requires an entitled key. |
| `include=forecast` | A paid event add-on. Adds a short outlook for eligible timed US events starting within seven days. Requires an entitled key. |
| `include=related` | A paid add-on on the single read of an event, class or camp. Adds `related: {similar, from_organization, at_place}`. `400` anywhere else. Requires an entitled key. |
| `include_mode=lenient` | Changes what happens when `include=` names something your key isn't entitled to: see below. |

`fields=` and `expand=` compose: `fields=expanded.place.name` works once
you've expanded `place`.

## When your key isn't entitled

`include=` add-ons require a key entitled to them (see
[Plans & access](https://api.tailend.dev/docs/plans-and-access.md)). Without one, the request fails:

```json
{ "error": { "code": "include_not_permitted", "message": "include=source is not available on this key's plan; retry without it, or add include_mode=lenient", "details": { "include": "source" }, "request_id": "req_2c6a19f8d0b34e77" } }
```

Add `include_mode=lenient` and the same request succeeds instead: `200`, with
the block left off and the omission recorded in `notices[]`:

```json
{ "data": [ "…" ], "meta": { "…": "…" }, "notices": [ { "code": "include_not_permitted", "include": "source", "message": "…" } ] }
```

A `200` in lenient mode doesn't mean you got everything you asked for:
always check `notices[]`.

## Related listings: `include=related`

The "more like this" rows for a listing page, in one request:

- `similar`: nearby listings of the same kind in the same Monday-to-Sunday
  week as this listing's date, in a matching category and for overlapping
  ages. Never this listing, its series, its organization or its place.
- `from_organization`: the organization's next upcoming listings of the same
  type, one card per series.
- `at_place`: other listings at the same place in the same week.

Up to six cards each. Every card carries `id`, `slug`, `type`, `name`, the
relevant occurrence (`starts_at`, `ends_at`, and the local dates `starts_on`,
`ends_on`), `place`, `image_url`, `price` and `is_free`. A related card is
always something the list endpoints would also return to your key. If a list
cannot be produced it comes back empty with a `related_unavailable` notice;
the listing itself is still returned.

## Forecasts: `include=forecast`

Forecasts use degrees Fahrenheit and miles per hour.

- Events within 48 hours receive hourly periods covering their start-to-end
  window; when no end is stated, the window is two hours.
- Later events, up to seven days out, get a summary of the event's local
  calendar day.
- Events without a time, coordinates, a US location, or a start within seven
  days omit `forecast`.
- When forecasts are temporarily unavailable the block is omitted and
  `notices[]` carries `forecast_unavailable`.
