{"openapi":"3.1.0","info":{"title":"StableShipping","description":"Buy US domestic shipping labels through Shippo. Quote rates with SIWX, then pay the selected label cost plus a fixed service fee with x402 on Base.","version":"1.0.0","x-guidance":"# StableShipping API\n\nStableShipping buys US domestic shipping labels through Shippo. Supported payment is x402 on Base only.\n\n## Flow\n\n1. POST /api/quote with SIWX to validate US sender/recipient addresses, create a Shippo shipment, and return available rates.\n2. Choose one returned rate by `rate_id`.\n3. POST /api/labels with x402 to buy the selected label. The price is the Shippo rate amount plus the fixed StableShipping service fee.\n4. GET /api/labels or GET /api/labels/{labelId} with SIWX to retrieve labels previously purchased by the signing wallet.\n5. GET /api/track/{labelId} with SIWX to refresh tracking for one purchased label.\n\n## Important Behavior\n\nStableShipping MVP supports US domestic shipments only. Both `address_from.country` and `address_to.country` must be `US`. International shipments and customs declarations are not supported yet.\n\nUse inches and pounds or ounces for parcels. The API accepts one parcel per shipment in MVP.\n\nAlways call POST /api/quote before buying a label. POST /api/labels accepts a Shippo `rate_id`, re-fetches the rate before payment, validates the final total against the configured maximum, and charges dynamically.\n\nPOST /api/labels requires `client_request_id` for idempotency. Reuse the same value only when retrying the same intended label purchase. A reused ID for another wallet or rate returns a conflict.\n\nShippo label URLs can expire. Store returned tracking information and use GET /api/labels/{labelId} to retrieve the latest stored label metadata.","guidance":"# StableShipping API\n\nStableShipping buys US domestic shipping labels through Shippo. Supported payment is x402 on Base only.\n\n## Flow\n\n1. POST /api/quote with SIWX to validate US sender/recipient addresses, create a Shippo shipment, and return available rates.\n2. Choose one returned rate by `rate_id`.\n3. POST /api/labels with x402 to buy the selected label. The price is the Shippo rate amount plus the fixed StableShipping service fee.\n4. GET /api/labels or GET /api/labels/{labelId} with SIWX to retrieve labels previously purchased by the signing wallet.\n5. GET /api/track/{labelId} with SIWX to refresh tracking for one purchased label.\n\n## Important Behavior\n\nStableShipping MVP supports US domestic shipments only. Both `address_from.country` and `address_to.country` must be `US`. International shipments and customs declarations are not supported yet.\n\nUse inches and pounds or ounces for parcels. The API accepts one parcel per shipment in MVP.\n\nAlways call POST /api/quote before buying a label. POST /api/labels accepts a Shippo `rate_id`, re-fetches the rate before payment, validates the final total against the configured maximum, and charges dynamically.\n\nPOST /api/labels requires `client_request_id` for idempotency. Reuse the same value only when retrying the same intended label purchase. A reused ID for another wallet or rate returns a conflict.\n\nShippo label URLs can expire. Store returned tracking information and use GET /api/labels/{labelId} to retrieve the latest stored label metadata.","contact":{"name":"Merit Systems","url":"http://localhost:3000"}},"servers":[{"url":"http://localhost:3000"}],"tags":[{"name":"Labels"},{"name":"Quote"},{"name":"Track"}],"paths":{"/api/labels":{"post":{"operationId":"labels_create","summary":"Buy a selected Shippo rate as a shipping label. The x402 price is the Shippo rate amount plus the fixed StableShipping service fee. Requires client_request_id for idempotency.","tags":["Labels"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0.25","max":"250.00"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_request_id":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[a-zA-Z0-9._:-]+$"},"rate_id":{"type":"string","minLength":1},"label_file_type":{"default":"PDF_4x6","type":"string","enum":["PDF","PDF_4x6","PNG","ZPLII"]},"metadata":{"type":"string","maxLength":100}},"required":["client_request_id","rate_id"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"shippo_transaction_id":{"type":"string"},"rate_id":{"type":"string"},"shipment_id":{"type":"string"},"carrier":{"type":"string"},"service":{"type":"string"},"service_token":{"type":"string"},"label_url":{"type":"string","format":"uri"},"label_file_type":{"type":"string"},"tracking_number":{"type":"string"},"tracking_url_provider":{"type":"string","format":"uri"},"eta":{"type":"string"},"shippo_amount":{"type":"number","minimum":0},"service_fee":{"type":"number","minimum":0},"charged_total":{"type":"number","minimum":0},"currency":{"type":"string"},"created_at":{"type":"string"}},"required":["id","status","rate_id","shippo_amount","service_fee","charged_total","currency","created_at"],"additionalProperties":false}}}},"402":{"description":"Payment Required"}}},"get":{"operationId":"labels_list","summary":"List labels purchased by the signing wallet.","tags":["Labels"],"security":[{"siwx":[]}],"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"in":"query","name":"per_page","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"labels":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"shippo_transaction_id":{"type":"string"},"rate_id":{"type":"string"},"shipment_id":{"type":"string"},"carrier":{"type":"string"},"service":{"type":"string"},"service_token":{"type":"string"},"label_url":{"type":"string","format":"uri"},"label_file_type":{"type":"string"},"tracking_number":{"type":"string"},"tracking_url_provider":{"type":"string","format":"uri"},"eta":{"type":"string"},"shippo_amount":{"type":"number","minimum":0},"service_fee":{"type":"number","minimum":0},"charged_total":{"type":"number","minimum":0},"currency":{"type":"string"},"created_at":{"type":"string"}},"required":["id","status","rate_id","shippo_amount","service_fee","charged_total","currency","created_at"],"additionalProperties":false}},"pagination":{"type":"object","properties":{"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"per_page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total_pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["page","per_page","total","total_pages"],"additionalProperties":false}},"required":["labels","pagination"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}},"/api/quote":{"post":{"operationId":"quote","summary":"Create a US domestic Shippo shipment and return available rates. Requires SIWX so the quote is stored for the signing wallet.","tags":["Quote"],"security":[{"siwx":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_request_id":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[a-zA-Z0-9._:-]+$"},"address_from":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"company":{"type":"string","maxLength":100},"street1":{"type":"string","minLength":1,"maxLength":100},"street2":{"type":"string","maxLength":100},"city":{"type":"string","minLength":1,"maxLength":64},"state":{"type":"string","minLength":2,"maxLength":2},"zip":{"type":"string","minLength":5,"maxLength":10},"country":{"default":"US","type":"string","const":"US"},"phone":{"type":"string","minLength":7,"maxLength":30},"email":{"type":"string","maxLength":100,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"is_residential":{"type":"boolean"}},"required":["name","street1","city","state","zip"]},"address_to":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"company":{"type":"string","maxLength":100},"street1":{"type":"string","minLength":1,"maxLength":100},"street2":{"type":"string","maxLength":100},"city":{"type":"string","minLength":1,"maxLength":64},"state":{"type":"string","minLength":2,"maxLength":2},"zip":{"type":"string","minLength":5,"maxLength":10},"country":{"default":"US","type":"string","const":"US"},"phone":{"type":"string","minLength":7,"maxLength":30},"email":{"type":"string","maxLength":100,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"is_residential":{"type":"boolean"}},"required":["name","street1","city","state","zip"]},"parcel":{"type":"object","properties":{"length":{"type":"number","exclusiveMinimum":0,"maximum":120},"width":{"type":"number","exclusiveMinimum":0,"maximum":120},"height":{"type":"number","exclusiveMinimum":0,"maximum":120},"distance_unit":{"default":"in","type":"string","const":"in"},"weight":{"type":"number","exclusiveMinimum":0,"maximum":150},"mass_unit":{"default":"lb","type":"string","enum":["lb","oz"]}},"required":["length","width","height","weight"]},"carrier_accounts":{"maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"metadata":{"type":"string","maxLength":100}},"required":["client_request_id","address_from","address_to","parcel"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"quote_id":{"type":"string"},"shippo_shipment_id":{"type":"string"},"rates":{"type":"array","items":{"type":"object","properties":{"rate_id":{"type":"string"},"shipment_id":{"type":"string"},"carrier":{"type":"string"},"service":{"type":"string"},"service_token":{"type":"string"},"amount":{"type":"number","minimum":0},"currency":{"type":"string"},"estimated_days":{"type":"integer","minimum":0,"maximum":9007199254740991},"duration_terms":{"type":"string"},"attributes":{"default":[],"type":"array","items":{"type":"string"}}},"required":["rate_id","shipment_id","carrier","service","amount","currency","attributes"],"additionalProperties":false}},"messages":{"default":[],"type":"array","items":{}},"expires_at":{"type":"string"}},"required":["quote_id","shippo_shipment_id","rates","messages","expires_at"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}},"/api/labels/{labelId}":{"get":{"operationId":"labels_get","summary":"Retrieve a stored shipping label by local label ID or Shippo transaction ID. Requires the wallet that bought the label.","tags":["Labels"],"security":[{"siwx":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"shippo_transaction_id":{"type":"string"},"rate_id":{"type":"string"},"shipment_id":{"type":"string"},"carrier":{"type":"string"},"service":{"type":"string"},"service_token":{"type":"string"},"label_url":{"type":"string","format":"uri"},"label_file_type":{"type":"string"},"tracking_number":{"type":"string"},"tracking_url_provider":{"type":"string","format":"uri"},"eta":{"type":"string"},"shippo_amount":{"type":"number","minimum":0},"service_fee":{"type":"number","minimum":0},"charged_total":{"type":"number","minimum":0},"currency":{"type":"string"},"created_at":{"type":"string"}},"required":["id","status","rate_id","shippo_amount","service_fee","charged_total","currency","created_at"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}},"/api/track/{labelId}":{"get":{"operationId":"track_get","summary":"Refresh tracking for a purchased label by local label ID or Shippo transaction ID. Requires the wallet that bought the label.","tags":["Track"],"security":[{"siwx":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"label_id":{"type":"string"},"tracking_number":{"type":"string"},"carrier":{"type":"string"},"status":{"type":"string"},"status_details":{"type":"string"},"tracking_history":{"default":[],"type":"array","items":{}}},"required":["label_id","tracking_number","carrier","tracking_history"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}}},"components":{"securitySchemes":{"siwx":{"type":"apiKey","in":"header","name":"SIGN-IN-WITH-X"}}}}