{
  "openapi": "3.1.0",
  "info": {
    "title": "Shipify Public API",
    "version": "1.0.0",
    "summary": "Read-only package-forwarding data for AI assistants and integrations.",
    "description": "Public, unauthenticated endpoints describing Shipify's package forwarding service from Budapest, Hungary: destinations, prices, optional services, and what may not be shipped.\n\nThere is no write API by design. An account can only be created by the customer in person, because sign-up carries the Terms of Service acceptance and the customs mandate. An assistant should pre-fill the sign-up form via `/api/signup-link` and hand the resulting link to the customer.\n\nAll endpoints allow cross-origin requests and are safe to call without user consent.",
    "contact": {
      "name": "Shipify support",
      "email": "hello@shipify.hu",
      "url": "https://shipify.hu"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://shipify.hu",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "discovery",
      "description": "What the service is and how to address a parcel."
    },
    {
      "name": "pricing",
      "description": "Published rates and quotes."
    },
    {
      "name": "compliance",
      "description": "Prohibited and restricted goods, size limits."
    },
    {
      "name": "handoff",
      "description": "Passing the customer a link to finish sign-up themselves."
    }
  ],
  "paths": {
    "/api/info": {
      "get": {
        "tags": [
          "discovery"
        ],
        "operationId": "getInfo",
        "summary": "Service descriptor",
        "description": "Start here. Describes the service, the required parcel address format, and every other endpoint.",
        "responses": {
          "200": {
            "description": "Service descriptor",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/countries": {
      "get": {
        "tags": [
          "pricing"
        ],
        "operationId": "listCountries",
        "summary": "Destinations and starting prices",
        "description": "Every country Shipify forwards to. Hungary is the origin, not a destination, and is not listed.",
        "responses": {
          "200": {
            "description": "Supported destinations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currency": {
                      "type": "string",
                      "const": "EUR"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "countries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "description": "ISO 3166-1 alpha-2"
                          },
                          "name_en": {
                            "type": "string"
                          },
                          "name_hu": {
                            "type": "string"
                          },
                          "from_price_eur": {
                            "type": "number"
                          },
                          "min_price_eur": {
                            "type": "number"
                          },
                          "per_kg_eur": {
                            "type": "number"
                          },
                          "eu": {
                            "type": "boolean",
                            "description": "Destination is in the EU customs union, so no customs clearance."
                          },
                          "transit_business_days": {
                            "type": "string",
                            "description": "Typical door-to-door range in business days, e.g. \"3–6\". Modelled on the lanes we run, not a carrier guarantee; customs clearance outside the EU can add days.",
                            "example": "3–6"
                          },
                          "page_url": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uri",
                            "description": "Landing page for the destination, when there is one. Null for the ~40 destinations that are served and priced but have no page of their own — the price and facts here are still complete."
                          }
                        },
                        "required": [
                          "code",
                          "name_en",
                          "from_price_eur",
                          "eu",
                          "transit_business_days"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/services": {
      "get": {
        "tags": [
          "pricing"
        ],
        "operationId": "listServices",
        "summary": "Optional extras and standing fees",
        "responses": {
          "200": {
            "description": "Extras and fees",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "fees": {
                      "type": "object",
                      "properties": {
                        "intake_fee_eur": {
                          "type": "number"
                        },
                        "consolidation_fee_eur": {
                          "type": "number"
                        }
                      }
                    },
                    "services": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "examples": [
                              "insurance",
                              "bubble-wrap"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name_en": {
                            "type": "string"
                          },
                          "price_per_package_eur": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/quote": {
      "get": {
        "tags": [
          "pricing"
        ],
        "operationId": "getQuote",
        "summary": "Price a forwarding job",
        "description": "Packages ship together as one consignment, so shipping is priced on the combined weight rather than per parcel. The result is an estimate from published rates; the binding price is calculated at forwarding from the measured weight and dimensions, and excludes customs duty and destination VAT.",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "Destination, ISO 3166-1 alpha-2. See /api/countries.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            },
            "example": "DE"
          },
          {
            "name": "weight_kg",
            "in": "query",
            "required": true,
            "description": "Weight of a single package in kilograms (0.1-31.5).",
            "schema": {
              "type": "number",
              "minimum": 0.1,
              "maximum": 31.5
            },
            "example": 2
          },
          {
            "name": "packages",
            "in": "query",
            "required": false,
            "description": "Number of packages consolidated into the shipment.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          },
          {
            "name": "services",
            "in": "query",
            "required": false,
            "description": "Comma-separated extra service codes or ids. See /api/services.",
            "schema": {
              "type": "string"
            },
            "example": "insurance,fragile-label"
          },
          {
            "name": "length_cm",
            "in": "query",
            "required": false,
            "description": "Length of a single package in centimetres. Give all three dimensions or none — couriers charge the greater of actual and volumetric weight (length x width x height / 5000), so a large light parcel costs more than its weight suggests.",
            "schema": {
              "type": "number",
              "minimum": 1,
              "example": 40
            }
          },
          {
            "name": "width_cm",
            "in": "query",
            "required": false,
            "description": "Width of a single package in centimetres. Give all three dimensions or none — couriers charge the greater of actual and volumetric weight (length x width x height / 5000), so a large light parcel costs more than its weight suggests.",
            "schema": {
              "type": "number",
              "minimum": 1,
              "example": 40
            }
          },
          {
            "name": "height_cm",
            "in": "query",
            "required": false,
            "description": "Height of a single package in centimetres. Give all three dimensions or none — couriers charge the greater of actual and volumetric weight (length x width x height / 5000), so a large light parcel costs more than its weight suggests.",
            "schema": {
              "type": "number",
              "minimum": 1,
              "example": 40
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Price breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currency": {
                      "type": "string",
                      "const": "EUR"
                    },
                    "destination": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "name_en": {
                          "type": "string"
                        },
                        "eu": {
                          "type": "boolean"
                        },
                        "transit_business_days": {
                          "type": "string",
                          "example": "3–6"
                        }
                      }
                    },
                    "actual_weight_kg": {
                      "type": "number",
                      "description": "Combined scale weight of all packages."
                    },
                    "volumetric_weight_kg": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Combined volumetric weight (length x width x height / 5000), or null when no dimensions were given."
                    },
                    "chargeable_weight_kg": {
                      "type": "number",
                      "description": "The weight the price is calculated from: the greater of actual and volumetric weight."
                    },
                    "size_class": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "enum": [
                        "standard",
                        "long",
                        "over_limit",
                        null
                      ],
                      "description": "Per package, from the dimensions (null without them). long: longest side over 150 cm or middle side over 76 cm, priced with a surcharge. over_limit: longest side over 175 cm or girth (length + 2*width + 2*height, longest side as length) over 300 cm."
                    },
                    "manual_quote_required": {
                      "type": "boolean",
                      "description": "True for an over_limit box. The published rates do not apply: shipping_eur and total_eur are null, and the forwarding request waits for an individual quote after the parcel is measured. Nothing is charged until the customer accepts it."
                    },
                    "pricing_basis": {
                      "type": "string",
                      "enum": [
                        "weight_curve",
                        "per_kg",
                        "minimum_price",
                        "manual_quote"
                      ]
                    },
                    "breakdown": {
                      "type": "object",
                      "properties": {
                        "intake_fee_eur": {
                          "type": "number"
                        },
                        "shipping_eur": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "Null when manual_quote_required is true."
                        },
                        "long_parcel_surcharge_eur": {
                          "type": "number",
                          "description": "Flat surcharge for long packages (size_class long), 0 otherwise."
                        },
                        "consolidation_eur": {
                          "type": "number"
                        },
                        "services_eur": {
                          "type": "number"
                        }
                      }
                    },
                    "total_eur": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Null when manual_quote_required is true."
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "disclaimer": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/restrictions": {
      "get": {
        "tags": [
          "compliance"
        ],
        "operationId": "getRestrictions",
        "summary": "Prohibited goods, restricted goods and package limits",
        "description": "Transcribed from the Terms of Service; https://shipify.hu/terms/ is the binding text.",
        "responses": {
          "200": {
            "description": "Restrictions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "prohibited": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "restricted": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "item": {
                            "type": "string"
                          },
                          "condition": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "package_limits": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/signup-link": {
      "get": {
        "tags": [
          "handoff"
        ],
        "operationId": "getSignupLink",
        "summary": "Build a pre-filled sign-up link for the customer",
        "description": "Encodes the customer's details into a sign-up URL so they do not have to retype them. This creates no account and no state: the customer must open the link and accept the Terms, choose a password, clear the security check and confirm their email address themselves. Do not attempt to complete those steps on their behalf.",
        "parameters": [
          {
            "name": "first_name",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "last_name",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "email"
            }
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "hu"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Link to hand to the customer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "creates_account": {
                      "type": "boolean",
                      "const": false
                    },
                    "human_steps_required": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "instructions_for_assistant": {
                      "type": "string"
                    },
                    "message_to_customer": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid parameters",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Destination not served",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unavailable": {
        "description": "Pricing data temporarily unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
