# Client gallery

Send clients a gallery of selects, collect their feedback inline, and deliver final high-res files the moment they approve — all through the API.

![A client proofing gallery built on the Playbook API](/img/examples/client-gallery.webp)

Live preview

**[Open the interactive preview →](/demos/client-gallery/index.html)**  ·  a self-contained `index.html` you can click through in your browser (open photos, favorite shots, switch tabs) or download.

## The flow[​](#the-flow "Direct link to The flow")

1. Build a board of selects and add the assets.
2. **Share** the board to get a client-facing link.
3. Collect feedback with **comments**.
4. Deliver approved originals via the **shared download** endpoint.

## 1. Create the selects board[​](#1-create-the-selects-board "Direct link to 1. Create the selects board")

```
curl -X POST "https://api.playbook.com/v1/$ORG/boards" \

  -H "Authorization: Bearer $PLAYBOOK_TOKEN" \

  -H "Content-Type: application/json" \

  -d '{ "title": "Acme x Studio — Round 1 selects" }'
```

Add the selects with [batch upload](/docs/examples/portfolio.md#2-add-work-to-the-board), passing the board's `token`.

## 2. Share it with the client[​](#2-share-it-with-the-client "Direct link to 2. Share it with the client")

```
curl -X POST "https://api.playbook.com/v1/$ORG/boards/round-1-selects/share" \

  -H "Authorization: Bearer $PLAYBOOK_TOKEN"
```

```
{ "data": { "url": "https://playbook.com/s/def456/round-1-selects" } }
```

Send that URL to the client. Shared board links carry every asset, its metadata, and (optionally) comments and downloads. See [Sharing & Publishing](/docs/guides/sharing_and_publishing.md).

## 3. Collect feedback[​](#3-collect-feedback "Direct link to 3. Collect feedback")

Clients leave feedback on the shared board in Playbook; read it back per asset to power a review thread in your own UI:

review\.ts

```
const ORG = "your-org";

const TOKEN = process.env.PLAYBOOK_TOKEN!;



async function getComments(assetToken: string) {

  const res = await fetch(

    `https://api.playbook.com/v1/${ORG}/assets/${assetToken}/comments`,

    { headers: { Authorization: `Bearer ${TOKEN}` } },

  );

  const { data } = await res.json(); // threaded: each comment may have `replies`

  return data;

}
```

Comments are threaded (replies nest under `replies`), which maps cleanly onto a proofing conversation. See [Comments](/docs/guides/comments.md).

## 4. Deliver on approval[​](#4-deliver-on-approval "Direct link to 4. Deliver on approval")

Once a client signs off, hand them the original file. Use the shared-download endpoint with the board's share slug:

deliver.ts

```
async function downloadUrl(assetToken: string, shareSlug: string) {

  const res = await fetch(

    `https://api.playbook.com/v1/shared/${ORG}/assets/${assetToken}/download?sharedlinkslug=${shareSlug}`,

    { headers: { Authorization: `Bearer ${TOKEN}` } },

  );

  const { data } = await res.json();

  return data.raw_url; // full-resolution original; data.display_url for preview

}
```

Gate the call behind your own "approved" state so originals only go out once the client accepts.

## Related[​](#related "Direct link to Related")

* [Sharing & Publishing](/docs/guides/sharing_and_publishing.md)
* [Comments](/docs/guides/comments.md)
* [Fetching Data](/docs/guides/fetching_data.md)
