The three buckets

Per client, sliding hour, HTTP 429 with {"error": "rate_limited"} when exhausted. A client is the caller’s address and client signature, or the OAuth client when a bearer is sent. The machine-readable copy is rate-limits.yaml.

BucketLimitCoversWhen exhausted
Quote80 an hourPOST /quote; MCP get_parcel_quote; the A2A skill; POST /agent/checkout-session, create_checkout_link and the A2A skill when they price live (no valid quote_id)429 rate_limited
Checkout status60 an hourGET /agent/checkout-session/{{session_id}}; MCP get_checkout_status; the A2A skill429 rate_limited
OAuth token20 an hourPOST /oauth/token429 slow_down
Every quote spends a live carrier rating that costs SMKlog money. One call per shipment; cache on your side; never poll. Reusing a quote_id in create_checkout_link spends nothing from the quote bucket, so quote once and hand off from that quote.

What spends nothing

track_parcel and get_price_index over MCP spend no quote allowance. GET /status and the discovery documents (/openapi.json, everything under /.well-known/) are public and cacheable for an hour.

What a 429 looks like

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{"error": "rate_limited",
 "message": "Too many Smart Quote API requests from this client. Try again later."}

No rate-limit or Retry-After headers are sent today. Buckets are sliding one-hour windows: after a 429, wait and retry later rather than immediately. Switching from REST to MCP does not add capacity; the buckets are shared.

A bucket of your own

A client that needs more than the public allowance holds OAuth 2.0 client_credentials, issued by hand: write to info@smklog.com as auth.md describes, exchange the credentials at POST https://quote-api.smklog.com/oauth/token (scope quote), and send the opaque bearer on POST /quote. The token lives one hour and buys a dedicated hourly quote bucket at the size agreed at registration. Discovery: authorization-server metadata.