Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: SMKlog Quote Quotes API
version: 1.4.0
summary: Live parcel rates from a US origin, a checkout handed to a human, and where that checkout stands.
description: 'Live parcel rates from USPS, UPS, FedEx and DHL Express for a single shipment sent from a US origin: inside the US, or to Canada, the UK, Germany or Australia.'
termsOfService: https://smklog.com/terms
contact:
name: SMKlog
email: info@smklog.com
url: https://smklog.com/developers/
x-publisher: SMKlog (SMKLOG-2022 LLC)
servers:
- url: https://quote-api.smklog.com
description: 'Production. There is no sandbox host: quoting is free and read-only, so production is the place to try it.'
security:
- {}
- clientCredentials:
- quote
tags:
- name: Quotes
description: Live parcel rate quotes from a US origin.
paths:
/quote:
post:
operationId: getParcelQuote
tags:
- Quotes
summary: Price one parcel from a US origin across USPS, UPS and FedEx (plus DHL Express…
description: 'Prices one shipment live against the carriers for the lane. Name the item in plain words and the packed box is estimated server-side (the estimate, its confidence and its assumptions come back in package); send length_cm, width_cm, height_cm, weight_kg and package_source "manual" to price an exact box instead. Up to five purchasable services come back, each a checkout total with the SMKlog fee inside and the carrier counter price beside it. One call per shipment: every call spends a live carrier rating.'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/QuoteRequest'
examples:
described:
summary: Item described in plain words; the box is estimated
value:
product: Yamaha FG800 acoustic guitar in a hard case
quantity: 1
from_postal_code: '07102'
to_postal_code: '30303'
measured:
summary: Exact packed box; no estimate
value:
product: paperback books
quantity: 1
from_postal_code: '07030'
to_postal_code: '33101'
length_cm: 30
width_cm: 22
height_cm: 12
weight_kg: 3.2
package_source: manual
responses:
'200':
description: Priced (mode parcel_label_ready, up to 5 rates), not a parcel (mode not_a_parcel, empty rates — SMKlog does not arrange pallet or freight shipments), more than one box (mode multiple_boxes, empty rates — quote each box on its own), or restricted (empty rates with an explanation).
content:
application/json:
schema:
$ref: '#/components/schemas/QuoteResponse'
examples:
priced:
summary: Priced parcel, two of up to five rates shown
value:
mode: parcel_label_ready
identified_product_title: Yamaha FG800 acoustic guitar in a hard case
quote_id: q_8f3c2e1a4b7d
package:
quantity: 1
length_cm: 112
width_cm: 48
height_cm: 20
weight_kg: 6.4
description: Hard case in a single carton with padding
confidence: medium
assumptions:
- Hard case packed in one carton with about 5 cm of padding on every side
rates:
- carrier: USPS
service: Ground Advantage
service_code: GroundAdvantage
amount: 38.42
retail_amount: 46.95
delivery_days: 4
delivery_window: 2-5 business days
delivery_estimated_date: null
currency: USD
- carrier: UPS
service: Ground
service_code: Ground
amount: 41.1
retail_amount: 67.35
delivery_days: 3
delivery_window: null
delivery_estimated_date: '2026-10-16'
currency: USD
dangerous_goods: null
source:
package: ai_estimate
rates: live_carrier
notAParcel:
summary: 'Past parcel limits: no rates, no offer'
value:
mode: not_a_parcel
identified_product_title: Honda CB500F motorcycle
package:
quantity: 1
length_cm: 210
width_cm: 80
height_cm: 110
weight_kg: 190
description: Crated motorcycle
confidence: medium
assumptions: []
rates: []
notice: This shipment is past parcel limits. SMKlog sells parcel labels only and does not arrange pallet or freight shipments.
dangerous_goods: null
source:
package: ai_estimate
rates: not_a_parcel
'400':
description: invalid_json, invalid_request, missing_required_fields (with a missing array), product_not_recognized (the text names no shippable item — name the thing itself), or postal validation failure.
content:
application/json:
schema:
$ref: '#/components/schemas/Problem'
example:
error: missing_required_fields
missing:
- to_postal_code
'422':
description: product_url_not_detected — the page did not identify an item.
content:
application/json:
schema:
$ref: '#/components/schemas/Problem'
example:
error: product_url_not_detected
message: Could not identify the product from this URL. Enter the product name or package dimensions manually.
missing:
- product
'429':
description: rate_limited. Slow down; the same buckets cover /quote and /mcp (about 80 quote requests an hour per client).
content:
application/json:
schema:
$ref: '#/components/schemas/Problem'
example:
error: rate_limited
message: Too many Smart Quote API requests from this client. Try again later.
components:
schemas:
Problem:
type: object
description: 'Every error answer on this host: a stable machine-readable code in error, a sentence for the human in message, and the missing field names when the code is missing_required_fields.'
required:
- error
properties:
error:
type: string
description: 'Stable code: invalid_json, invalid_request, missing_required_fields, product_not_recognized, product_url_not_detected, session_failed, session_not_found, rate_limited, invalid_token'
message:
type: string
description: What went wrong, in a sentence
missing:
type: array
items:
type: string
description: Field names still needed, with missing_required_fields and product_not_recognized
Rate:
type: object
description: 'One purchasable service. Two prices are returned and they are not interchangeable: amount is the checkout total a customer pays, with the SMKlog fee inside it (the fee is itemized only on the checkout receipt), and retail_amount is the carrier’s own counter price for the same parcel where the carrier publishes one (0 where it does not).'
required:
- carrier
- service
- amount
- currency
properties:
carrier:
type: string
enum:
- USPS
- UPS
- FedEx
- DHL
description: USPS, UPS, FedEx or DHL
service:
type: string
description: Service display name, e.g. Ground Advantage
service_code:
type: string
description: Carrier service code, stable across calls
amount:
type: number
description: Checkout total, USD, SMKlog fee inside
retail_amount:
type: number
description: Carrier retail counter price, USD; 0 when not published
delivery_days:
type:
- integer
- 'null'
description: Transit days the carrier quoted, null when it quoted none
delivery_window:
type:
- string
- 'null'
description: e.g. "2-5 business days"; null when the carrier quoted none
delivery_estimated_date:
type:
- string
- 'null'
description: ISO date the carrier estimates, null when it gives none
currency:
type: string
enum:
- USD
description: Always USD
QuoteRequest:
type: object
description: One shipment to price. Name the item in plain words (the packed box is estimated) or send the four packed measurements and skip the estimate.
required:
- quantity
- from_postal_code
- to_postal_code
properties:
product:
type: string
maxLength: 2000
description: Plain-words item description, e.g. "Yamaha FG800 acoustic guitar in a hard case". Required unless product_url is given. Drives the box and weight estimate when dimensions are omitted. Text that names no shippable item answers 400 product_not_recognized.
product_url:
type: string
format: uri
description: Store product page URL; the item is identified from the page. Alternative to product.
quantity:
type: integer
minimum: 1
default: 1
description: How many of the item ship together. Default 1. Units the estimate packs into one box are priced as that box; units that need more than one box, or a quantity above 1 sent with exact dimensions (those describe one box), return mode multiple_boxes with empty rates.
from_postal_code:
type: string
pattern: ^[0-9]{5}$
description: 5-digit US ZIP; the origin is always in the United States.
to_postal_code:
type: string
maxLength: 12
description: 5-digit US ZIP when to_country_code is US or omitted; otherwise the destination country's own postal code.
to_country_code:
type: string
enum:
- US
- CA
- GB
- DE
- AU
default: US
description: 'Destination country. Sold online: US, CA, GB, DE, AU; any other answers mode international_unsupported_online with no rates.'
length_cm:
type: number
minimum: 1
maximum: 300
description: Packed box length. Supply all four of length_cm, width_cm, height_cm, weight_kg to skip the estimate.
width_cm:
type: number
minimum: 1
maximum: 300
description: Packed box width, cm.
height_cm:
type: number
minimum: 1
maximum: 300
description: Packed box height, cm.
weight_kg:
type: number
minimum: 0.1
maximum: 1000
description: Packed weight, kg. Online pricing stops at 68 kg (150 lb), 274 cm (108 in) on the longest side and 419 cm (165 in) of length plus girth; beyond that the response is mode not_a_parcel.
package_source:
type: string
enum:
- manual
description: Set to "manual" when supplying exact dimensions.
QuoteResponse:
type: object
description: A priced parcel, or a parcel the service will not price with the reason spelled out in mode. Only mode parcel_label_ready carries rates.
required:
- mode
- rates
properties:
mode:
type: string
enum:
- parcel_label_ready
- not_a_parcel
- multiple_boxes
- international_unsupported_online
- parcel_restricted
- review
- parcel_rates_unavailable
description: 'parcel_label_ready with up to 5 rates; not_a_parcel (empty rates: SMKlog does not arrange pallet or freight shipments); multiple_boxes (empty rates: quote each box on its own); international_unsupported_online; parcel_restricted and review (empty rates with an explanation); parcel_rates_unavailable (no carrier answered).'
identified_product_title:
type: string
description: What the estimator understood the item to be
quote_id:
type:
- string
- 'null'
pattern: ^q_[A-Za-z0-9-]{8,80}$
description: Handle to this quote, good for 15 minutes. Pass it to createPaymentSession as quote_id and that call reuses these rates instead of spending a second carrier call. Null when nothing was priced or the handle could not be stored; absent on answers that carry no rates.
package:
$ref: '#/components/schemas/Package'
packages:
type: array
items:
$ref: '#/components/schemas/Package'
description: Every box the estimate produced; one entry when the shipment is one parcel
rates:
type: array
maxItems: 5
items:
$ref: '#/components/schemas/Rate'
description: Up to five purchasable services, best value first
dangerous_goods:
type:
- object
- 'null'
description: 'Present when the item matched a dangerous-goods rule: the rule, the carrier restriction and what the human must confirm at checkout'
additionalProperties: true
sources:
type: array
items:
type: object
properties:
title:
type: string
url:
type: string
format: uri
description: Product pages the estimate read, when a search informed it
notice:
type:
- string
- 'null'
description: Human-readable reason when mode is not parcel_label_ready
source:
type: object
description: Where the package estimate and the rates came from
properties:
package:
type: string
description: manual, catalog, or the estimator that produced the box
rates:
type: string
description: live_carrier for live carrier rating, not_a_parcel when nothing was priced
additionalProperties: true
additionalProperties: true
Package:
type: object
description: 'The packed box used for pricing: what the estimator (or the caller) said the parcel measures, with the confidence and the assumptions behind an estimate.'
properties:
quantity:
type: integer
minimum: 1
description: Units packed into this box
length_cm:
type: number
description: Packed length, cm
width_cm:
type: number
description: Packed width, cm
height_cm:
type: number
description: Packed height, cm
weight_kg:
type: number
description: Packed weight, kg
description:
type: string
description: What the box holds, in a few words
confidence:
type: string
enum:
- low
- medium
- high
- manual
description: How sure the estimate is; manual when the caller supplied the measurements
assumptions:
type: array
items:
type: string
description: What the estimate took for granted, for the human to correct before paying
securitySchemes:
clientCredentials:
type: oauth2
description: 'Optional. Every operation works without a token. A client that wants its own hourly rate-limit bucket holds OAuth 2.0 client_credentials issued by hand (registration instructions at https://smklog.com/auth.md) and sends the opaque bearer it gets from /oauth/token. Discovery: /.well-known/oauth-authorization-server.'
flows:
clientCredentials:
tokenUrl: https://quote-api.smklog.com/oauth/token
scopes:
quote: Price parcels and prepare checkouts from a dedicated per-client rate-limit bucket
externalDocs:
description: 'Developer portal: docs, schemas, playground, rate limits, status'
url: https://smklog.com/developers/
x-provenance:
method: published
publisher: SMKlog (SMKLOG-2022 LLC)
source: https://quote-api.smklog.com/openapi.json
published: '2026-10-12'
x-mcp:
transport: streamable-http
endpoint: https://quote-api.smklog.com/mcp
serverCard: https://quote-api.smklog.com/.well-known/mcp/server-card.json