Addons are carrier integrations that extend checkout with features like parcel-shop pickers and shipment tracking. YNS supports three shipping addons:

- **GLS** — GLS Poland (ADE-Plus WebAPI). Connectable via API.
- **InPost** — InPost Paczkomat (ShipX v1). Connectable via API.
- **Furgonetka** — Multi-carrier broker. Connects via OAuth in the admin panel only; the API can read status and disconnect it.

Once connected, link a carrier to a shipping method by passing `addonName` when creating or updating a [Shipping Method](/docs/api-reference/shipping).

## List Addons

```
GET /api/v1/addons
```

Returns all connected addons plus any API-managed shipping addons that are not yet connected (so you can discover what to enable).

### Query Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `type` | `string` | Filter by addon category: `shipping`, `analytics`, `products`, `invoicing`, or `orders` |

### Response

```json
{
  "data": [
    {
      "name": "gls",
      "type": "shipping",
      "connected": true,
      "manageable": true,
      "environments": {
        "live": { "configured": true },
        "test": { "configured": false }
      },
      "config": {
        "labelMode": "one_label_on_a4_pdf"
      },
      "createdAt": "2024-08-01T12:00:00.000Z",
      "updatedAt": "2024-08-01T12:00:00.000Z"
    },
    {
      "name": "inpost",
      "type": "shipping",
      "connected": false,
      "manageable": true,
      "environments": null,
      "config": null,
      "createdAt": null,
      "updatedAt": null
    },
    {
      "name": "furgonetka",
      "type": "shipping",
      "connected": false,
      "manageable": false,
      "environments": null,
      "config": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "meta": { "count": 3 }
}
```

### Response Fields

| Field | Type | Description |
|-------|------|-------------|
| `name` | `string` | Addon identifier (`gls`, `inpost`, `furgonetka`) |
| `type` | `string` | Addon category (currently always `shipping`) |
| `connected` | `boolean` | Whether the addon has been configured for this store |
| `manageable` | `boolean` | Whether the API can connect/disconnect this addon (`false` for Furgonetka — OAuth only) |
| `environments` | `object \| null` | Per-environment status (`live`/`test`), each with `configured: boolean` |
| `config` | `object \| null` | Addon-specific configuration. GLS returns `{ labelMode }`, InPost returns `{ fallbackTemplate }`. |

---

## Get GLS Addon

```
GET /api/v1/addons/gls
```

Returns the GLS addon status for the authenticated store.

### Response

```json
{
  "name": "gls",
  "type": "shipping",
  "connected": true,
  "manageable": true,
  "environments": {
    "live": { "configured": true },
    "test": { "configured": false }
  },
  "config": {
    "labelMode": "one_label_on_a4_pdf"
  },
  "createdAt": "2024-08-01T12:00:00.000Z",
  "updatedAt": "2024-08-01T12:00:00.000Z"
}
```

---

## Connect GLS Addon

```
PUT /api/v1/addons/gls
```

Saves GLS ADE WebAPI credentials for the specified environment. Credentials are verified against the GLS API before being stored.

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `environment` | `"live"` \| `"test"` | Yes | Which store environment these credentials are for |
| `login` | `string` | Yes | GLS ADE WebAPI login (a dedicated API login, not the ADE panel login) |
| `password` | `string` | Yes | GLS ADE WebAPI password. Write-only — never returned by the API. |
| `trackApiUser` | `string` | No | Track & Trace API user (a separate GLS-issued pair). Omit to disable status polling. |
| `trackApiPassword` | `string` | No | Track & Trace API password |
| `labelMode` | `string` | No | Store-wide label format. See [Label Modes](#gls-label-modes). |

### GLS Label Modes

| Value | Description |
|-------|-------------|
| `one_label_on_a4_pdf` | Single label on an A4 PDF |
| `four_labels_on_a4_pdf` | Four labels on an A4 PDF |
| `four_labels_on_a4_right_pdf` | Four labels on the right side of an A4 PDF |
| `roll_160x100_pdf` | 160x100mm roll label (PDF) |
| `roll_160x100_zebra` | 160x100mm roll label (Zebra ZPL) |
| `roll_160x100_zebra_epl` | 160x100mm roll label (Zebra EPL) |
| `roll_160x100_datamax` | 160x100mm roll label (Datamax DPL) |

```bash
curl -X PUT \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"environment": "live", "login": "my_api_login", "password": "my_api_pass"}' \
  https://your-store.yns.store/api/v1/addons/gls
```

### Response (200)

Returns the updated addon status (same shape as [Get GLS Addon](#get-gls-addon)).

### Error Responses

| Status | Description |
|--------|-------------|
| `400` | Invalid request data or GLS rejected the credentials |
| `502` | GLS ADE could not verify the credentials — try again shortly |

---

## Disconnect GLS Addon

```
DELETE /api/v1/addons/gls
```

Disconnects GLS entirely, or clears credentials for a single environment.

### Query Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `environment` | `"live"` \| `"test"` | Clear only this environment's credentials (keeps the addon connected). Omit to disconnect entirely. |

```bash
# Disconnect entirely
curl -X DELETE \
  -H "Authorization: Bearer your_api_key" \
  https://your-store.yns.store/api/v1/addons/gls

# Clear only test credentials
curl -X DELETE \
  -H "Authorization: Bearer your_api_key" \
  "https://your-store.yns.store/api/v1/addons/gls?environment=test"
```

### Response (200)

```json
{
  "ok": true,
  "deleted": 1
}
```

### Error Responses

| Status | Description |
|--------|-------------|
| `404` | GLS is not connected to this store |
| `409` | Cannot disconnect because shipping methods still use it. Delete or unlink those shipping methods first. |

---

## Get InPost Addon

```
GET /api/v1/addons/inpost
```

Returns the InPost addon status for the authenticated store. Same response shape as GLS, with `config.fallbackTemplate` instead of `config.labelMode`.

### Response

```json
{
  "name": "inpost",
  "type": "shipping",
  "connected": true,
  "manageable": true,
  "environments": {
    "live": { "configured": true },
    "test": { "configured": false }
  },
  "config": {
    "fallbackTemplate": "medium"
  },
  "createdAt": "2024-08-01T12:00:00.000Z",
  "updatedAt": "2024-08-01T12:00:00.000Z"
}
```

---

## Connect InPost Addon

```
PUT /api/v1/addons/inpost
```

Saves InPost ShipX credentials for the specified environment. Credentials are verified against the ShipX API before being stored.

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `environment` | `"live"` \| `"test"` | Yes | Which store environment these credentials are for |
| `token` | `string` | Yes | ShipX API token from the InPost Parcel Manager API tab. Write-only. |
| `orgId` | `string` | Yes | InPost organization ID from the Parcel Manager |
| `geowidgetToken` | `string` | No | Geowidget token for the checkout map tab. Omitting or blanking this **clears** a stored token — resend it on every update. |
| `fallbackTemplate` | `string` | No | Store-wide fallback parcel size: `small`, `medium`, or `large`. Used when creating a shipment without an explicit `template` and product dimensions can't determine one. Environment-independent. |

```bash
curl -X PUT \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"environment": "live", "token": "shipx_token", "orgId": "12345", "fallbackTemplate": "medium"}' \
  https://your-store.yns.store/api/v1/addons/inpost
```

### Response (200)

Returns the updated addon status.

### Error Responses

| Status | Description |
|--------|-------------|
| `400` | Invalid request data or InPost rejected the credentials |
| `502` | ShipX could not verify the credentials — try again shortly |

---

## Disconnect InPost Addon

```
DELETE /api/v1/addons/inpost
```

Same behavior as [Disconnect GLS Addon](#disconnect-gls-addon) — supports the `environment` query parameter.

---

## Get Furgonetka Addon

```
GET /api/v1/addons/furgonetka
```

Returns the Furgonetka addon status. Furgonetka connects via OAuth in the admin panel, so the API can only read its status.

---

## Connect Furgonetka Addon

```
PUT /api/v1/addons/furgonetka
```

Returns `400` — Furgonetka connects via OAuth and cannot be enabled with an API key. Connect it in the admin: Add-ons > Furgonetka. Once connected, you can list its status, link shipping methods to it, and disconnect it via the API.

---

## Disconnect Furgonetka Addon

```
DELETE /api/v1/addons/furgonetka
```

Disconnects the Furgonetka OAuth integration from the store.

### Response (200)

```json
{
  "ok": true,
  "deleted": 1
}
```

### Error Responses

| Status | Description |
|--------|-------------|
| `404` | Furgonetka is not connected to this store |
| `409` | Cannot disconnect because shipping methods still use it |

---

## InstaView Account Images

```
GET /api/v1/instaview/accounts/:handle/images
```

Returns the Instagram images mirrored into YNS for a connected InstaView account, newest first. The handle is matched case-insensitively and a leading `@` is ignored.

### Query Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | `number` | 48 | Images per page (max 96) |
| `cursor` | `string` | — | Cursor from the previous response's `nextCursor` |

```bash
curl \
  -H "Authorization: Bearer your_api_key" \
  "https://your-store.yns.store/api/v1/instaview/accounts/acmecandles/images?limit=24"
```

### Response

```json
{
  "handle": "acmecandles",
  "images": [
    {
      "id": "0191abc0-1234-7def-8000-00000000000c",
      "url": "https://cdn.example.com/instaview/acme/abc123.jpg",
      "description": "New winter collection just landed",
      "takenAt": "2024-05-04T09:12:00.000Z",
      "code": "C6xYzAbCdEf",
      "mediaId": "17912345678901234"
    }
  ],
  "nextCursor": "eyJpZCI6IjAxOTFhYmMwIn0"
}
```

Pass `nextCursor` back as `cursor` to fetch the next page. A `null` `nextCursor` means you've reached the end.

### Errors

| Status | Meaning |
|--------|---------|
| `404` | No InstaView account matches the handle |