# Container images
URL: https://openship.io/docs/api/images.md

Browse container images for project services.

import { TypeTable } from 'fumadocs-ui/components/type-table';

The Images API returns the **build-image catalog** — the curated list of ready-made service images
(PostgreSQL, Redis, and friends) you pick from when adding a service to a project. In the dashboard this is
the image grid in the **Add service** modal; it's a read-only lookup, so there's nothing to create or edit.

<Callout title="Catalog comes from Openship Cloud" type="info">
The module is available on every deploy mode (self-hosted, cloud, and desktop), but the catalog itself is
served by Openship Cloud. On a **SaaS** instance it uses the master catalog; on a **self-hosted** instance
with a cloud account linked it uses your org's cloud token. On a self-hosted instance with **no** cloud
link, the endpoint returns an empty list with `cloudConnected: false` rather than an error — the dashboard
falls back to the "Custom image" tile. Results are cached in memory for a few minutes.
</Callout>

## List images

Returns the catalog for your organization. Both filters are optional and applied by the upstream catalog;
omit them to get everything.

```
GET /api/images
```

<TypeTable
  type={{
    search: { type: 'string', description: 'Free-text filter matched against catalog entries (query parameter).', required: false },
    category: { type: 'string', description: 'Restrict to one category, e.g. "database", "cache", "messaging" (query parameter).', required: false },
  }}
/>

```bash
curl "$OPENSHIP_URL/api/images" \
  -H "Authorization: Bearer $OPENSHIP_TOKEN"

# With filters:
curl "$OPENSHIP_URL/api/images?search=postgres&category=database" \
  -H "Authorization: Bearer $OPENSHIP_TOKEN"
```

The response is `{ "success": true, "images": [ … ] }`. Each entry describes one catalog image; common fields
are `id` (slug you pick), `name` (display name), `image` (the Docker image string), `description`,
`category`, `logo`, `tags`, `ports`, and `defaultEnv` (suggested env keys). Additional fields returned by the
upstream catalog are passed through unchanged for forward compatibility.

## Errors

<Callout title="Empty catalog with cloudConnected: false" type="info">
Not an error. On a self-hosted instance with no cloud account linked, the response is
`{ "success": true, "images": [], "cloudConnected": false }`. Link a cloud account to populate the catalog,
or supply a custom image directly on the service.
</Callout>

<Callout title="500 — failed to list images" type="warn">
The upstream catalog call failed. The response is `{ "success": false, "error": "…" }`. Retry after a
moment; the result is cached once fetched.
</Callout>

<Callout title="401 — unauthorized" type="error">
No valid session cookie or bearer token was supplied. Create a token with
[`openship token create`](/docs/cli/access) and send it as `Authorization: Bearer <token>`.
</Callout>

## Operations

{/* api-operations:start */}

| Operation | REST API |
| --- | --- |
| List available build/service images, optionally filtered by `?search=` and `?category=`. | `GET /api/images`<br />`Authenticated` |

{/* api-operations:end */}
