# CORS, HEAD and OPTIONS

Use the API from browsers and HTTP clients.

Source: [CORS, HEAD and OPTIONS](/http/)

## CORS [#cors]

Responses allow every browser origin with `Access-Control-Allow-Origin: *` and expose `ETag` to JavaScript through `Access-Control-Expose-Headers: ETag`. Every feed can therefore be read directly from a browser, with no key.

## HEAD [#head]

Every external GET route accepts HEAD and returns the corresponding GET status, ETag, cache policy, content type and CORS headers with no response body, including failures and conditional `304`. A `304` has no content type. Body-length and per-request headers can differ; `Content-Length` may be omitted.

```bash
curl --fail --silent --show-error --head 'https://api.live.storyos.ai/v1/fixtures/0042500401/feeds/pulse'
```

## OPTIONS [#options]

OPTIONS on any path returns `204` with no body. A successful preflight does not establish that the path exists.

```bash
curl --silent --show-error --include --request OPTIONS \
  --header 'Origin: https://example.com' \
  --header 'Access-Control-Request-Method: GET' \
  --header 'Access-Control-Request-Headers: If-None-Match, Authorization' \
  'https://api.live.storyos.ai/v1/fixtures/0042500401/feeds/pulse'
```

| Preflight header               | Value                          |
| ------------------------------ | ------------------------------ |
| `Access-Control-Allow-Methods` | `GET, HEAD, OPTIONS`           |
| `Access-Control-Allow-Headers` | `If-None-Match, Authorization` |
| `Access-Control-Max-Age`       | `86400`                        |

The browser may cache that preflight for up to 86,400 seconds; this is separate from caching the feed response.
