---
title: GET /api/unfurl
description: Best-effort OpenGraph metadata for an external link, used only to render the editor's embed-card preview. Auth-gated and SSRF-guarded.
---

<Note>

This is an editor-support route — it renders the embed-card preview in the Write canvas. There's no CLI command, and it never changes what gets saved (the stored content keeps the bare link so Medium unfurls it natively on import).

</Note>

Returns best-effort OpenGraph metadata for an external link. Auth-gated so it isn't an open fetch proxy, and guarded against obvious SSRF (only `http`/`https`; no localhost or private ranges).

## Endpoint

```text
GET https://scripto.codika.io/api/unfurl?url=<encoded-url>
```

## Auth

`Authorization: Bearer scripto_…` (or a session).

## Query parameters

| Param | Type | Description |
|---|---|---|
| `url` | string | The external link to preview. Must be `http`/`https` and not a private host. |

## Response (200)

```json
{
  "success": true,
  "data": {
    "url": "https://example.com/post",
    "host": "example.com",
    "title": "Post title",
    "description": "OpenGraph description…",
    "image": "https://example.com/og.png"
  }
}
```

## Errors

| HTTP | `code` | Cause |
|---|---|---|
| 400 | `invalid-argument` | Missing/invalid `url`, non-http(s), or a blocked private host. |
| 401 | `unauthenticated` | Missing or invalid key. |
| 404 | `not-found` | The link returned a non-OK status. |
| 500 | `internal` | Could not fetch the link. |

## curl

```bash
curl -sS -G "https://scripto.codika.io/api/unfurl" \
  --data-urlencode "url=https://example.com/post" \
  -H "Authorization: Bearer $SCRIPTO_API_KEY"
```

## Next

- **[API overview](/api-reference/overview)** — the full endpoint index.
