# List the public product catalog

`GET /v1/public/products`

URL: https://docs.spacerun.co/docs/platform/reference/public-site/listPublicProducts

- **Operation ID:** `listPublicProducts`
- **Tags:** Public site
- **Base URL:** `http://localhost:8787`

Active, public plans and credit packs ordered by `sort_order`. Returned as a bare array.

**Workflow:** [Integration guide](https://docs.spacerun.co/docs/platform/guides/support-and-public-api).

**Authentication:** none (public).

## Authentication

- **Auth:** none (public endpoint, no token required).

## Responses

### 200

Product catalog.

- Header `x-request-id`: Request identifier; quote it when reporting an error.
Content type: `application/json`

Schema: `(object (PublicProduct))[]`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `[].id` | `string<uuid>` | yes | - |
| `[].key` | `string` | yes | - |
| `[].name` | `string` | yes | - |
| `[].description` | `string \| null` | yes | - |
| `[].type` | `string` | yes | Product type, e.g. a subscription plan or `credit_pack`. |
| `[].tier_key` | `string` | yes | - |
| `[].credits_included` | `integer` | yes | - |
| `[].features` | `any` | no | Marketing feature list; shape defined by the catalog. |
| `[].sort_order` | `integer` | yes | - |
| `[].highlight` | `boolean` | yes | - |
| `[].badge` | `string \| null` | yes | - |
| `[].pack_credits` | `integer \| null` | yes | Credit packs only. |
| `[].pack_bonus_credits` | `integer \| null` | yes | Credit packs only. |
| `[].pack_expires_after` | `string \| null` | yes | Credit packs only; Postgres interval text. |
| `[].default_stripe_price_id` | `string \| null` | yes | - |
| `[].prices` | `any` | no | Price list for the product (Stripe price ids, currency, amounts). |

## Errors

### 500

Unexpected server error (`internal`). No details are returned.

- Header `x-request-id`: Request identifier; quote it when reporting an error.
Content type: `application/json`

Schema: `object (ErrorBody)`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | `string` | yes | Stable machine-readable error code, e.g. `forbidden`, `not_found`. |
| `details` | `any` | no | Optional structured context. For 403 it is `{ perm }`. |

**Error response**

```json
{
  "error": "internal"
}
```

## Examples

### curl

```bash
curl -X GET 'http://localhost:8787/v1/public/products'
```

### TypeScript

```ts
const response = await fetch("http://localhost:8787/v1/public/products", {
  method: "GET",
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const data = response.status === 204 || response.status === 205
  ? undefined
  : response.headers.get("content-type")?.includes("json")
    ? await response.json()
    : await response.text();
```
