# Shipping cost and delivery declared

> A purchase agent that cannot compute the delivered total cannot complete a checkout, and returns to the merchant without it.

- Source: /checks/shipping-costs
- Site: AgenticWebScore
- Language: English

---
A purchase agent that cannot compute the delivered total cannot complete a checkout, and returns to the merchant without it.

| Property | Value |
| --- | --- |
| Check id | `shipping-costs` |
| Dimension | Commerce Protocols (15%) |
| Tier | Recommended — pool 20 pts |
| Weight inside tier | 2 |
| Impact | High |
| Maturity | Adopted — A ratified standard with real deployment. |
| Conditional | No |
| Publishing skill | `shipping-costs` |
| Standards | schema.org/OfferShippingDetails |

## What the scanner requests

- `/shipping`
- `/returns`

It also reads documents it has already fetched: `$home`.

## What is measured

Profile-scoped: reported as not scored and excluded from the denominator unless the e-commerce or marketplace profile has been positively identified, and this check never creates that identification itself. In scope, the scanner inspects the `shippingDetails` of the Offers it holds and passes when that OfferShippingDetails carries a `shippingRate` MonetaryAmount with `value` and `currency` and a `deliveryTime` ShippingDeliveryTime with `handlingTime` and `transitTime` QuantitativeValues; a rate without a delivery window, or a delivery window without a rate, is a partial (0.7), and neither is a fail.

## Reproduce it yourself

You do not have to take our word for any of this. Run the same measurement against your own domain:

```bash
DOMAIN=shop.example.com
curl -sL "https://$DOMAIN/" | perl -0777 -ne 'while (m{<script[^>]*application/ld\+json[^>]*>(.*?)</script>}gsi) { print "$1\n" }' | jq -r '.. | objects | select((."@type"? | if type == "array" then .[] else . end) == "OfferShippingDetails") | [(.shippingRate.value // "NO rate"), (.shippingRate.currency // "NO currency"), (.deliveryTime.handlingTime.maxValue // "NO handlingTime"), (.deliveryTime.transitTime.maxValue // "NO transitTime")] | @tsv'
```

## The fix

This is the artifact to ship. It is the complete change, not a description of one.

```json
{
  "@context": "https://schema.org",
  "@type": "Offer",
  "url": "https://shop.example.com/products/aurora-desk-lamp",
  "price": "1299.00",
  "priceCurrency": "USD",
  "availability": "https://schema.org/InStock",
  "shippingDetails": {
    "@type": "OfferShippingDetails",
    "shippingRate": { "@type": "MonetaryAmount", "value": "49.00", "currency": "USD" },
    "deliveryTime": {
      "@type": "ShippingDeliveryTime",
      "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
      "transitTime": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 5, "unitCode": "DAY" }
    }
  }
}
```

> Free shipping still needs an explicit shippingRate with value "0.00" rather than an omitted rate, because a purchase agent computes the delivered total from this node and an absent rate reads as unknown rather than as free.

## Standards referenced

- `schema.org/OfferShippingDetails`

## Related checks

| Check | Tier | Impact | Same skill |
| --- | --- | --- | --- |
| `product-schema` — Product/catalog schema | Essential | Critical | — |
| `payment-protocols` — Agent payment standard support (AP2/ACP/x402/UCP) | Recommended | High | — |
| `agent-purchase` — Agent purchase policy | Recommended | High | — |
| `ucp-manifest` — UCP manifest (/.well-known/ucp) | Emerging | Medium | — |
| `returns` — Return and shipping terms machine-readable | Recommended | Medium | — |
| `agent-analytics` — Agent traffic measurement | Emerging | Low | — |
| `inventory-freshness` — Inventory and price freshness | Recommended | High | — |
| `seller-identity` — Seller identity declared | Recommended | Medium | — |
