> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zeroclick.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agentify REST quickstart

> Mint an agentify:convert key, convert a page with curl, and read the response: the document, the cache headers, ETag revalidation, and every error.

This page converts one marketing page over plain HTTP. The [SDK middleware](/agentify/sdk-middleware) wraps the same call in detection and fail-open serving; use REST when you drive the conversion yourself.

<Steps>
  <Step title="Mint a key with the agentify:convert scope">
    In the [dashboard](https://dashboard.zeroclick.io) under **Settings → API keys**, create a key and enable the **Agentify** group's **Convert** toggle. The secret is shown once; store it immediately:

    ```sh theme={null}
    ZEROCLICK_AGENTIFY_KEY=zc_…
    ```

    The scope grants `GET /v1/agentify/markdown` and nothing else. Keys are minted in a signed-in session only.
  </Step>

  <Step title="Convert a page">
    Pass the page as the `url` query parameter, with the key as a bearer token:

    ```sh theme={null}
    curl "https://api.zeroclick.io/v1/agentify/markdown?url=https://www.acme.com/pricing" \
      -H "Authorization: Bearer $ZEROCLICK_AGENTIFY_KEY"
    ```

    The first conversion of a page runs the full pipeline — fetch, headless render when the page needs JavaScript, cleanup — and takes a few seconds. Repeats serve from cache for about a day.
  </Step>

  <Step title="Name the seller, if your organization has several">
    The document inlines one seller's storefront. An organization with exactly one active seller never names it; with several, pass the seller's id (the `sel_…` value from your dashboard store URL):

    ```sh theme={null}
    curl "https://api.zeroclick.io/v1/agentify/markdown?url=https://www.acme.com/pricing&seller=sel_x7f2kq93bh0d" \
      -H "Authorization: Bearer $ZEROCLICK_AGENTIFY_KEY"
    ```

    Ambiguity answers `400 seller_required` rather than guessing between storefronts.
  </Step>
</Steps>

## The response

A success is `200` with the markdown document as the body — front matter, then your storefront inlined, then the page content, as shown on the [overview](/agentify/overview#the-document) — and cache headers meant to be reused downstream:

| Header          | Value                                                  |
| --------------- | ------------------------------------------------------ |
| `content-type`  | `text/markdown; charset=utf-8`                         |
| `cache-control` | `public, max-age=86400, stale-while-revalidate=604800` |
| `etag`          | A hash of the exact body served.                       |

Forward `cache-control` and `etag` when you serve the markdown from your own site — that is what lets your CDN cache the rendered markdown in front of you. Send `Vary: accept, user-agent` alongside them, so a shared cache never hands the markdown to a browser. The SDK middleware does all of this for you.

Revalidate a stored copy with the ETag; an unchanged document answers `304` with no body:

```sh theme={null}
curl -i "https://api.zeroclick.io/v1/agentify/markdown?url=https://www.acme.com/pricing" \
  -H "Authorization: Bearer $ZEROCLICK_AGENTIFY_KEY" \
  -H 'If-None-Match: "1f7d1c0a4b9e2d83f5a6c7b8d9e0f1a2"'
```

## Errors

Every error is JSON with a machine code in `error`:

| Status | Code                    | Meaning                                                                                                                                    |
| ------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| 400    | `invalid_url`           | The `url` is not a public `http(s)` page. IP literals, credentials, non-standard ports, and non-public hostnames are rejected.             |
| 400    | `seller_required`       | Your organization has zero or several active sellers, or the `seller` parameter matched none of them. Pass `?seller=sel_…`.                |
| 403    | `insufficient_scope`    | The key lacks `agentify:convert`.                                                                                                          |
| 403    | `auth_type_not_allowed` | The endpoint accepts API keys only; a dashboard session cannot call it.                                                                    |
| 422    | `content_too_thin`      | The page converted to too little readable content — usually a JavaScript app serving an empty shell. See [SPA setup](/agentify/spa-setup). |
| 502    | `fetch_failed`          | The page could not be fetched: DNS, TLS, a network failure, too many redirects, or an oversized body.                                      |

A page that answers with an error status still converts: a `404` page becomes a markdown document like any other, so a stale link on your site degrades to a readable page rather than a failed conversion.

Requests beyond 60 per minute per organization answer `429`. Conversions are cached for a day at every layer, so steady traffic stays far below the limit; if you prewarm many pages at once, pace the loop.

## Next steps

<Columns cols={2}>
  <Card title="SDK middleware" icon="package" href="/agentify/sdk-middleware">
    Detection, the same call, and fail-open serving as drop-in middleware.
  </Card>

  <Card title="SPA setup" icon="zap" href="/agentify/spa-setup">
    Mount the same contract in an edge function in front of a CDN-hosted SPA.
  </Card>
</Columns>
