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

# Show company logos in your app

> Render a mark for any domain straight from an image tag, with no fetching, storing, or resizing on your side.

<Note>
  **Have an agent build it.** Copy the brief below into Claude Code, Cursor, or any coding agent with access to your project. It states the calls, the questions worth asking you first, and the mistakes to avoid.
</Note>

<Accordion title="Agent brief">
  ```text theme={null}
  Implement this blueprint in my project:
  https://docs.hydrafetch.com/blueprints/directory-logos

  Read that page, inspect this project's stack, then build the flow end to end.

  Add company logos to a directory UI using the Hydrafetch image endpoint.

  For browser rendering: an img tag pointed at https://img.hydrafetch.com/logo/{domain} with a publishable key as the token query parameter, plus size and an optional fallback parameter. No credits, no server round trip. For server side use where metadata is needed: GET /v1/web/brand/logo?domain={domain}&theme=light|dark&type=icon|wordmark with the X-API-Key header, 1 credit, returning url, format, width, height and dominantColor.

  Ask me before writing code:
  - What pixel size is the logo rendered at, and is it on a light or dark surface? Does the interface have both themes?
  - Should a missing logo render a generated monogram or fall through to our own placeholder component?
  - Is this browser-side only, or does something server side need the file and its metadata?
  - Which domains are allowed to use the publishable key?
  - Do we know the domains ahead of time, so they can be warmed in the background after an import?

  The response shape for the API call: data with domain, url, kind, variant, format, width, height, dominantColor. data is null when we hold no mark.

  Size the request from the device pixel ratio, so a 32 pixel avatar on a 2x display requests 64. Reserve a fixed box with an aspect ratio so rows do not reflow as logos arrive. The first request for an unseen domain resolves on the spot and takes a few seconds, and every request after it is immediate, so render a placeholder background and let the image swap in rather than blocking the layout. Restrict the publishable key to our domains, since it is readable in client markup.

  Notes: use the publishable key in markup and never the secret API key. Choose the variant that suits the background, and switch it with the theme. Served image URLs are edge cached for up to a day, so revoking a key does not immediately stop cached URLs. Keep the secret API key on the server and never ship it in client code.
  ```
</Accordion>

Directories, CRMs, dashboards and vendor lists all need a logo next to a company name. The usual answer is a scraper, an S3 bucket, a resize pipeline, and a placeholder for everything that failed.

There is an image endpoint that removes all four. Point an `img` tag at it.

## The pipeline

### 1. Render the mark directly

```html theme={null}
<img src="https://img.hydrafetch.com/logo/stripe.com?token=YOUR_PUBLISHABLE_KEY&size=128"
     alt="Stripe" />
```

The URL is public and immutable, so it can go straight into your markup, an email template, or a PDF. No signing, no proxying, no bucket.

### 2. Use a publishable key in the browser

Browser traffic uses a publishable key restricted to your domains, not your secret API key. It is metered on its own allowance and never spends credits, which is what makes it safe to put in client-side markup.

### 3. Decide what a missing logo looks like

By default a domain we hold no mark for returns a generated monogram, so the tag always renders something. Ask for a 404 instead when you would rather draw your own fallback.

### 4. Fetch it server side when you need the metadata

When you need the file itself, or its dimensions and dominant colour, `GET /v1/web/brand/logo` returns the asset with its details for 1 credit.

## The first request for a new domain

A domain nobody has asked for before is resolved on the spot, and that first request waits rather than answering with a placeholder.

The wait is bounded. Past the budget the resolve finishes in the background, that one request gets the fallback, and the next request is served from storage. So a cold domain takes a few seconds once and every request after it is immediate.

This shapes where you put the call. In a list view rendering fifty companies, most will be warm and a few may not be, so give the image a placeholder background and let it swap in rather than blocking a layout on it. If you know the domains ahead of time, such as after an import, request them once in the background and the customer never meets a cold one.

## Getting the rendering right

Ask for the `size` you actually draw at. Requesting 512 to display at 32 wastes bandwidth on every row of every page, and on a directory that is most of the page weight.

Account for retina. A 32 pixel avatar on a 2x display wants a 64 pixel image, so size from the device pixel ratio rather than the CSS pixel.

Pick the variant for the background you are drawing on. A light mark on a light card is an empty box, and this is the single most common way this goes wrong. If your interface has both themes, the logo has to switch with them.

Reserve the space. Give the image a fixed box with an aspect ratio so the row does not jump when it loads, since a directory that reflows as logos arrive feels broken even when everything worked.

## Choosing the fallback deliberately

By default a domain with no mark returns a generated monogram, so the tag always renders something.

That is right for most directories, since a consistent shape in every row looks intentional. Set `fallback=404` instead when you want to draw your own placeholder, and handle the error on the image element.

Do not let a missing logo look like a broken page. Whichever route you pick, the empty state should be a designed state.

## Operating it

The image URL is public and immutable, so it can go anywhere: your markup, an email template, a PDF export. Nothing to sign, nothing to proxy, no bucket to keep.

Restrict the publishable key to your domains. It is going into client-side markup where anyone can read it, and the domain restriction is what stops it being used elsewhere.

Remember the edge cache when you rotate a key. Once a URL has been served it is cached at the edge for up to a day, so revoking a key does not immediately stop already-cached URLs from loading.

Reach for the API call only when you need more than pixels. `GET /v1/web/brand/logo` returns the file with its dimensions and dominant colour for 1 credit, which is what you want when generating an email template or picking a background to sit the mark on.

## What it costs

The image endpoint does not spend credits. It runs on a separate allowance tied to your publishable key, because a logo in a list view is not the same kind of request as a scrape.

The server side logo call is 1 credit. A full brand record is 5, so reach for it only when you want more than the mark.

## What to watch for

Set `size` to what you actually render. Asking for 512 to display at 32 wastes bandwidth on every row of every page.

Pick the variant for your background. A light mark on a light card is an empty box, and this is the single most common way this goes wrong.

Remember the edge cache. Once a URL has been served it is cached at the edge for up to a day, so revoking a key does not immediately stop already-cached URLs from loading.
