# /link-title

1 route.

Naming a link without storing anything: the page title the apps show when someone attaches a link. App sessions only.

## POST /v1/link-title

Look up a link’s page title (app session only; nothing is stored)

What the apps call to name a link a person is attaching, when the device cannot read the page itself (a browser cannot, because of CORS). The server fetches the page once, behind the same outbound-fetch guard as webhook delivery: public addresses only, the connection pinned to the address it checked, every redirect checked again (at most 5), 8 seconds in all, at most 256 KB read, `text/html` only. `http://` links are fetched over https. It returns the page’s `og:title`, else its `<title>`, and keeps NOTHING: no row, no cache, and no log line carries the URL or the title. The caller stores the title, encrypted, if it wants it. A page that cannot be read answers 200 with `title: null`, never an error. ⚠ First-party only: an access key or a connected app is refused, whatever its scopes; to capture a link with its title, use `POST /inbox`.

**Scopes**: any valid credential  
**First-party only.** Not callable with an access key or an OAuth token, whatever scopes it holds.

**Request body**

| field | type | | notes |
|---|---|---|---|
| `url` | string | required | max 2048 chars, min 1 |

**Response**

- **200** [LinkTitle](/objects#linktitle). The title, or `null`, and the host of the URL sent.

**Errors**: [grant_expired](/errors/grant_expired) * [grant_revoked](/errors/grant_revoked) * [unauthorized](/errors/unauthorized) * [forbidden_scope](/errors/forbidden_scope) * [payload_too_large](/errors/payload_too_large) * [unsupported_media_type](/errors/unsupported_media_type) * [validation_failed](/errors/validation_failed) * [rate_limited](/errors/rate_limited) * [internal](/errors/internal)
