# Shipping · Admin

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /shipping/admin/providers

**List supported shipping providers**

`operationId: ShippingController_getShippingProviderTypes`

The carrier provider types the platform supports — EasyPost, Shippo, FedEx and so on — each with a description and setup help. This is a platform-level list and takes no org.

#### Signature

```http
GET /shipping/admin/providers () -> Supported provider types
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- The only endpoint here that does not read the `orgid` header — the list is the same for every org.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /shipping/admin/integrations`

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Supported provider types |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /shipping/admin/integrations

**Get configured shipping integrations**

`operationId: ShippingController_getShippingIntegrations`

The carrier integrations this org has configured, alongside the providers still available to add.

#### Signature

```http
GET /shipping/admin/integrations () -> Configured integrations and available providers
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /shipping/admin/providers`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Configured integrations and available providers |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /shipping/admin/configs

**List shipping configurations**

`operationId: ShippingController_listShippingConfigs`

All shipping rate configurations for the org. One is the site default; the rest are selected per product or per config name.

#### Signature

```http
GET /shipping/admin/configs () -> The org's shipping configurations
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/configs`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The org's shipping configurations |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/configs

**Create a shipping configuration**

`operationId: ShippingController_createShippingConfig`

Creates a rate configuration. `method` picks the pricing model and decides which of the other blocks matter:

- `free` — no charge.
- `flat` — a fixed rate, optionally per item. Uses `flatRate`.
- `weight` — banded by weight. Uses the weight tiers and `defaultRate`.
- `zone` — banded by destination.
- `carrier` — live rates from the configured carrier. Uses `carrier` and `origin`.

`freeShipping` and `handling` apply on top of any method.

#### Signature

```http
POST /shipping/admin/configs (body) -> The created configuration
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- `name` is the identifier for every other config endpoint, so pick it carefully — there is no rename.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/configs/{name}`
- `POST /shipping/admin/preview-rate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The configuration to create.

```json
{
  "name": "standard-flat",
  "title": "Standard shipping",
  "method": "flat",
  "isDefault": true,
  "currency": "USD",
  "flatRate": {
    "rate": 4.99,
    "perItem": false
  },
  "freeShipping": {
    "enabled": true,
    "threshold": 75
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created configuration |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /shipping/admin/configs/{name}

**Get a shipping configuration**

`operationId: ShippingController_getShippingConfig`

Fetches one shipping configuration by name, including its rate rules, free-shipping threshold and handling fees.

#### Signature

```http
GET /shipping/admin/configs/{name} (name: string) -> The shipping configuration
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | CONFIG_NOT_FOUND | Shipping configuration not found | No config in the org has that name. | List them with `GET /shipping/admin/configs`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/configs/{name}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `name` | path | string | yes | Shipping config name (slug). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The shipping configuration |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Shipping configuration not found — No config in the org has that name. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/configs/{name}

**Update a shipping configuration**

`operationId: ShippingController_updateShippingConfig`

Updates an existing configuration. Note this is a `POST`, not a `PUT` — the whole config admin surface uses `POST` for writes, including delete.

#### Signature

```http
POST /shipping/admin/configs/{name} (name: string, body) -> The updated configuration
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Test a change with `POST /shipping/admin/preview-rate` before making it the default.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | CONFIG_NOT_FOUND | Shipping configuration not found | No config has that name. | Check the name with `GET /shipping/admin/configs`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/preview-rate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `name` | path | string | yes | Shipping config name (slug). |

### Request body

The fields to change.

```json
{
  "flatRate": {
    "rate": 5.99,
    "perItem": false
  },
  "freeShipping": {
    "enabled": true,
    "threshold": 100
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated configuration |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Shipping configuration not found — No config has that name. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/configs/delete/{name}

**Delete a shipping configuration**

`operationId: ShippingController_deleteShippingConfig`

Deletes a shipping configuration.

Note the unusual shape: deletion is a `POST` to `/delete/{name}` rather than a `DELETE`. Products still pointing at the deleted config fall back to the site default.

#### Signature

```http
POST /shipping/admin/configs/delete/{name} (name: string) -> Confirmation of the delete
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Check which products reference the config before deleting — they silently fall back to the default.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | CONFIG_NOT_FOUND | Shipping configuration not found | No config has that name. | Check the name first. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/configs/set-default/{name}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `name` | path | string | yes | Shipping config name (slug). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Confirmation of the delete |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Shipping configuration not found — No config has that name. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/configs/set-default/{name}

**Set the default shipping configuration**

`operationId: ShippingController_setDefaultShippingConfig`

Makes one configuration the site default — what applies to any product that does not name its own. Setting a new default clears the flag on the previous one.

#### Signature

```http
POST /shipping/admin/configs/set-default/{name} (name: string) -> Confirmation
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | CONFIG_NOT_FOUND | Shipping configuration not found | No config has that name. | Check the name first. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /shipping/admin/configs`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `name` | path | string | yes | Shipping config name (slug). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Confirmation |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Shipping configuration not found — No config has that name. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/product/shipping

**Update shipping settings for a product**

`operationId: ShippingController_updateProductShipping`

Sets a product's shipping settings — its dimensions, weight, and which shipping config applies to it.

#### Signature

```http
POST /shipping/admin/product/shipping (body) -> Confirmation
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Weight and dimensions matter for `weight`-method configs and for live carrier rates — a product without them will be quoted badly.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/products/shipping`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The product and its shipping settings.

```json
{
  "productId": "DRK-COLA-330",
  "shipping": {
    "config": "standard-flat",
    "weight": 0.8,
    "length": 3,
    "width": 3,
    "height": 5
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Confirmation |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/products/shipping

**Bulk update product shipping settings**

`operationId: ShippingController_bulkUpdateProductShipping`

Applies the same shipping settings to many products at once — the practical way to move a whole category onto a new shipping config.

#### Signature

```http
POST /shipping/admin/products/shipping (body) -> Confirmation
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- The same settings go to every product — send dimensions only when they genuinely apply to all of them.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/product/shipping`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The products and the settings to apply to all of them.

```json
{
  "productIds": [
    "DRK-COLA-330",
    "DRK-COLA-500"
  ],
  "shipping": {
    "config": "standard-flat"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Confirmation |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/preview-rate

**Preview a rate calculation**

`operationId: ShippingController_previewShippingRate`

Runs a shipping configuration against a test parcel and returns what it would charge, without creating any record or contacting a carrier for a real quote.

This is how a rate change gets verified before it reaches customers. Omit `configName` to test the default, and pass `productPrice` so any free-shipping threshold is exercised too.

#### Signature

```http
POST /shipping/admin/preview-rate (body) -> The rate the configuration would charge
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Writes nothing and buys nothing — safe to call as often as you like.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/configs/{name}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The configuration and the test parcel.

```json
{
  "configName": "standard-flat",
  "productPrice": 40,
  "parcel": {
    "length": 12,
    "width": 9,
    "height": 4,
    "weight": 2.5
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The rate the configuration would charge |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /shipping/admin/calculate-packing

**Preview how items would be packed**

`operationId: ShippingController_calculatePacking`

Shows how items would be distributed into boxes without creating a shipment — which box sizes get used and what goes in each.

Pass an `orderNumber` to pack the order's items, or supply `items` inline to test a hypothetical basket. Useful for checking box sizes are configured sensibly before a rate quote surprises you.

#### Signature

```http
POST /shipping/admin/calculate-packing (body) -> The packing breakdown, with box assignments
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /shipping/admin/preview-rate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

What to pack. Send an order number or items, not both.

```json
{
  "orderNumber": "A7K2M9QX4"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The packing breakdown, with box assignments |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /shipping/admin/stats

**Get shipping statistics**

`operationId: ShippingController_getShippingStats`

Aggregate shipping figures for the org — volume, spend and carrier mix.

#### Signature

```http
GET /shipping/admin/stats () -> Aggregate shipping statistics
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /shipping/list`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Aggregate shipping statistics |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

