---
title: "Save an extracted component to the catalog"
method: POST
path: "/api/admin/save-component"
tags: ["admin-catalog-tools"]
---

# Save an extracted component to the catalog

`POST /api/admin/save-component`

## Request

- Base URL: `https://voltplan.app`
- URL: `https://voltplan.app/api/admin/save-component`
- Auth: HTTP bearer

Creates a `components` record (always `preferred_suggestion: false`; null and empty fields are dropped). `brand` is a brand name that is matched or created in `component_brands`. An `icon` data URI is uploaded as a `<slugified-name>.png` file; any other `icon` string is stored as-is. Each `affiliate_links` entry becomes an `affiliate_links` record. Brand and per-link failures do not fail the request; they are reported in `warnings`. The route performs no input validation of its own, so invalid input surfaces as 500.

## Request body

- AdminCatalogSaveComponentRequest: Mirrors `ComponentData` in `src/app/api/admin/save-component/route.ts`. Optional fields accept `null` because the extract response is sent verbatim. Unknown keys are ignored.
  - `name` string, required
  - `type` 'battery' | 'charger' | 'inverter' | 'transformer' | 'power' | 'load' | 'fuse' | 'shunt' | 'switch' | 'disconnect' | 'tool', required
  - `voltage_in` number, nullable
  - `voltage_in_type` 'ac' | 'dc' | 'null', nullable
  - `voltage_out` number, nullable
  - `voltage_out_type` 'ac' | 'dc' | 'null', nullable
  - `watt` number, nullable
  - `estd_price_euro` number, nullable
  - `description` string, nullable
  - `image` string, nullable
  - `icon` string, nullable: A data URI is uploaded as a PNG file; any other string is stored as-is.
  - `duty_cycle` number, nullable
  - `default_utilization_factor` number, nullable
  - `usage_hours_per_day` number, nullable
  - `amperage` number, nullable
  - `cutoff_voltage` number, nullable
  - `fuse_type` string, nullable
  - `wire_gauge` string, nullable
  - `brand` string, nullable: Brand name, matched or created in `component_brands`.
  - `affiliate_links` AdminCatalogSaveAffiliateLink[], nullable
    - `url` string, required
    - `country` string, required

## Response `200`

Component created.

- AdminCatalogSaveComponentResponse
  - `success` unknown, required
  - `componentId` string, required: Id of the new `components` record.
  - `message` 'Component saved successfully', required
  - `warnings` string[]: Non-fatal problems (brand or affiliate-link creation failed). Omitted when empty.

## Other responses

- `403`: Admin access required. Returned for a missing, invalid or expired bearer token as well as for a valid token whose user lacks `is_admin=true`; admin endpoints never answer 401.
- `500`: Malformed JSON body, PocketBase rejected the `components` record (e.g. missing `name` or `type`), or admin credentials not configured. `warnings` collected before the failure are included.

---

[API](https://skmtc.dev/voltplan/apis/voltplan-api.md) · [All operations](https://skmtc.dev/voltplan/apis/voltplan-api/llms.txt) · [OpenAPI document](https://skmtc.dev/voltplan/apis/voltplan-api/revisions/575b86a7af92?raw)
