{
  "openapi": "3.1.0",
  "info": {
    "title": "Printen.eu Reseller API",
    "version": "1.1.0",
    "description": "Sell Printen.eu products in your own store. Orders are paid from your prepaid balance or saved card and shipped white label (your name, no Printen.eu branding, no prices) to your customer. Amounts are in euro cents. Errors always have the shape {\"error\": {\"code\", \"message\", \"details\"?}}; messages are in English. Send your own User-Agent header (for example \"MyShop-Integration/1.0\"): some generic library defaults such as Python-urllib are blocked by our CDN before they reach the API."
  },
  "servers": [
    {
      "url": "https://www.printen.eu/api/reseller/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/products": {
      "get": {
        "summary": "List catalogue products",
        "description": "Required scope: `catalog:read` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "A page of products",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "limit": {
                      "type": "integer",
                      "description": "Page size actually used."
                    },
                    "maxLimit": {
                      "const": 100
                    },
                    "limitCapped": {
                      "type": "boolean",
                      "description": "true when the requested limit was above 100."
                    },
                    "requestedLimit": {
                      "type": "integer"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Search term"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Storefront category slug"
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "nl",
                "en",
                "de",
                "fr"
              ],
              "default": "nl"
            },
            "description": "Language of names and options"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "description": "1-100 (default 25). Larger values are capped at 100; the response reports limit and limitCapped."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Value of nextCursor from the previous page"
          }
        ]
      }
    },
    "/products/{id}": {
      "get": {
        "summary": "Get a product with options and file requirements",
        "description": "Required scope: `catalog:read` (keys without scopes have all scopes). {id} is the product id or its slug in any language (nl/en/de/fr). Returns the customer options with their defaults and allowed values, and how quantity works for this product.",
        "responses": {
          "200": {
            "description": "The product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProductDetail"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "Unknown product",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Product id or slug"
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "nl",
                "en",
                "de",
                "fr"
              ]
            },
            "description": "Language"
          }
        ]
      }
    },
    "/quotes": {
      "post": {
        "summary": "Price lines for a destination country",
        "description": "Required scope: `quotes:write` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "Quote incl. discount, VAT and shipping",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Quote"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422": {
            "description": "The request is well-formed but cannot be fulfilled: invalid or automatic option keys, invalid values, option conflicts, quantity/copies mismatch, unavailable run size, file not PDF/PNG/JPG, unknown product or SKU, or a combination our print partner cannot price. See error.details.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "lines",
                  "country"
                ],
                "properties": {
                  "lines": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/LineInput"
                    }
                  },
                  "country": {
                    "type": "string",
                    "description": "ISO-2"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/reseller-products": {
      "get": {
        "summary": "List your own products",
        "description": "Required scope: `reseller-products:read` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "A page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ResellerProduct"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "limit": {
                      "type": "integer",
                      "description": "Page size actually used."
                    },
                    "maxLimit": {
                      "const": 100
                    },
                    "limitCapped": {
                      "type": "boolean",
                      "description": "true when the requested limit was above 100."
                    },
                    "requestedLimit": {
                      "type": "integer"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Search SKU or title"
          },
          {
            "name": "active",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "Filter"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "description": "Page size"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Value of nextCursor from the previous page"
          }
        ]
      },
      "post": {
        "summary": "Create your own product (SKU with fixed options)",
        "description": "Required scope: `reseller-products:write` (keys without scopes have all scopes).",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ResellerProduct"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409": {
            "description": "SKU exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422": {
            "description": "Invalid product or options",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResellerProductInput"
              }
            }
          }
        }
      }
    },
    "/reseller-products/{id}": {
      "get": {
        "summary": "Get your own product (id or SKU)",
        "description": "Required scope: `reseller-products:read` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "The product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ResellerProduct"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "patch": {
        "summary": "Update your own product",
        "description": "Required scope: `reseller-products:write` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ResellerProduct"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409": {
            "description": "SKU exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422": {
            "description": "Invalid options",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResellerProductPatch"
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete your own product",
        "description": "Required scope: `reseller-products:write` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "deleted": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409": {
            "description": "Still linked to a connected store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/orders": {
      "get": {
        "summary": "List your orders (newest first)",
        "description": "Required scope: `orders:read` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "A page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "limit": {
                      "type": "integer",
                      "description": "Page size actually used."
                    },
                    "maxLimit": {
                      "const": 100
                    },
                    "limitCapped": {
                      "type": "boolean",
                      "description": "true when the requested limit was above 100."
                    },
                    "requestedLimit": {
                      "type": "integer"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "AWAITING_FUNDS",
                "AWAITING_FILE",
                "PAYMENT_FAILED",
                "SUBMITTED",
                "CANCELLED"
              ]
            },
            "description": "Reseller order state"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "PAID",
                "PROCESSING",
                "PRINTING",
                "SHIPPED",
                "DELIVERED",
                "CANCELLED",
                "REFUNDED"
              ]
            },
            "description": "Production status"
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "API",
                "DASHBOARD",
                "SHOPIFY",
                "WOOCOMMERCE",
                "ETSY",
                "WIX",
                "TIKTOK_SHOP",
                "AMAZON"
              ]
            },
            "description": "Order source"
          },
          {
            "name": "externalOrderId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Your order id"
          },
          {
            "name": "createdFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "From"
          },
          {
            "name": "createdTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "To"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "description": "Page size"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Value of nextCursor from the previous page"
          }
        ]
      },
      "post": {
        "summary": "Place an order",
        "description": "Required scope: `orders:write` (keys without scopes have all scopes).",
        "responses": {
          "201": {
            "description": "Order created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OrderResult"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "200": {
            "description": "Repeat of an earlier request with the same Idempotency-Key (duplicate: true)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OrderResult"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400": {
            "description": "Invalid body or missing Idempotency-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422": {
            "description": "The request is well-formed but cannot be fulfilled: invalid or automatic option keys, invalid values, option conflicts, quantity/copies mismatch, unavailable run size, file not PDF/PNG/JPG, unknown product or SKU, or a combination our print partner cannot price. See error.details.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Unique per order, e.g. your own order id. Retrying with the same key never creates a second order."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderInput"
              }
            }
          }
        }
      }
    },
    "/orders/{id}": {
      "get": {
        "summary": "Get an order",
        "description": "Required scope: `orders:read` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "The order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Order"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Order id, resellerOrderId or order number"
          }
        ]
      }
    },
    "/orders/{id}/cancel": {
      "post": {
        "summary": "Cancel an order while it has not reached production",
        "description": "Required scope: `orders:write` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "The order after cancellation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Order"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409": {
            "description": "Too late to cancel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/wallet": {
      "get": {
        "summary": "Balance and ledger entries",
        "description": "Required scope: `wallet:read` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "Wallet",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "balanceCents": {
                          "type": "integer"
                        },
                        "currency": {
                          "const": "EUR"
                        },
                        "entries": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "type": {
                                "type": "string",
                                "enum": [
                                  "TOPUP",
                                  "AUTO_TOPUP",
                                  "ORDER_CHARGE",
                                  "ORDER_REFUND",
                                  "ADJUSTMENT"
                                ]
                              },
                              "amountCents": {
                                "type": "integer"
                              },
                              "balanceAfterCents": {
                                "type": "integer"
                              },
                              "orderId": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "note": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time"
                              }
                            }
                          }
                        },
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    },
                    "limit": {
                      "type": "integer",
                      "description": "Page size actually used."
                    },
                    "maxLimit": {
                      "const": 100
                    },
                    "limitCapped": {
                      "type": "boolean",
                      "description": "true when the requested limit was above 100."
                    },
                    "requestedLimit": {
                      "type": "integer"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "description": "Page size"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Value of nextCursor from the previous page"
          }
        ]
      }
    },
    "/webhooks": {
      "get": {
        "summary": "List webhook endpoints",
        "description": "Required scope: `webhooks:read` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "Endpoints",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a webhook endpoint (the secret is only returned here)",
        "description": "Required scope: `webhooks:write` (keys without scopes have all scopes).",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/WebhookEndpoint"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "secret": {
                              "type": "string",
                              "description": "whsec_..., shown once"
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400": {
            "description": "Invalid url or events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409": {
            "description": "Too many endpoints",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Public https URL"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "order.created",
                        "order.submitted",
                        "order.awaiting_funds",
                        "order.payment_failed",
                        "order.in_production",
                        "order.shipped",
                        "order.delivered",
                        "order.cancelled",
                        "order.file_problem"
                      ]
                    },
                    "description": "Empty or omitted = all events"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "summary": "Delete a webhook endpoint",
        "description": "Required scope: `webhooks:write` (keys without scopes have all scopes).",
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "deleted": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "403": {
            "description": "Account not approved/suspended, or key lacks the scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    }
  },
  "webhooks": {
    "orderEvent": {
      "post": {
        "summary": "Order event sent to your endpoint",
        "description": "Headers: X-Printen-Event (type), X-Printen-Delivery (delivery id), X-Printen-Timestamp (unix seconds), X-Printen-Signature (`v1=` + hex HMAC-SHA256 of `${timestamp}.${rawBody}` with your endpoint secret). Respond with 2xx within 10 s. Failed deliveries are retried with backoff for about 24 hours. Events can arrive more than once; dedupe on `id`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "prk_live_... (live) or prk_test_... (sandbox: nothing is charged or produced)"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "unauthorized, forbidden, not_found, rate_limited, invalid_request (400: malformed body), idempotency_key_required, invalid_options, invalid_lines, invalid_file_url, unknown_product, unknown_sku, product_unavailable, price_unavailable, unsupported_country, cannot_cancel, internal_error, ..."
              },
              "message": {
                "type": "string",
                "description": "English, human readable. With several problems it describes the first; see details."
              },
              "details": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              },
              "retryAfterSeconds": {
                "type": "integer"
              }
            }
          }
        }
      },
      "FileRequirements": {
        "type": "object",
        "properties": {
          "required": {
            "type": "boolean"
          },
          "formats": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "minDpi": {
            "type": "integer"
          },
          "colorProfile": {
            "type": "string"
          },
          "bleedMm": {
            "type": "number"
          },
          "fileUrlMustBeHttps": {
            "type": "boolean"
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "image": {
            "type": [
              "string",
              "null"
            ]
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "url": {
            "type": "string"
          },
          "fileRequirements": {
            "$ref": "#/components/schemas/FileRequirements"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Option": {
        "type": "object",
        "required": [
          "key",
          "label",
          "type",
          "default"
        ],
        "description": "A customer option exactly as the product page shows it. Only these keys may be sent in options; everything else (production method, sheet size, bundling, packaging, ...) is set automatically.",
        "properties": {
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string",
            "description": "In the requested lang."
          },
          "type": {
            "type": "string",
            "enum": [
              "select",
              "number",
              "text"
            ]
          },
          "required": {
            "type": "boolean"
          },
          "default": {
            "type": [
              "string",
              "number",
              "null"
            ],
            "description": "Used when you leave the option out; the same start value as the product page."
          },
          "values": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "unavailable": {
                  "type": "boolean",
                  "description": "Temporarily not available from our print partner."
                }
              }
            }
          },
          "min": {
            "type": "number"
          },
          "max": {
            "type": "number"
          },
          "visibleWhen": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Only applies when these other options have one of these values."
          },
          "customSize": {
            "type": "object",
            "description": "Free size: set this option to `value` and send width/height in centimetres under widthKey/heightKey.",
            "properties": {
              "value": {
                "type": "string"
              },
              "widthKey": {
                "type": "string"
              },
              "heightKey": {
                "type": "string"
              },
              "unit": {
                "const": "cm"
              }
            }
          }
        }
      },
      "ProductDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Product"
          },
          {
            "type": "object",
            "properties": {
              "slugs": {
                "type": "object",
                "description": "Slug per language (nl/en/de/fr). The product id is the stable key; any of these slugs also works in GET /products/{id}.",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "options": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Option"
                }
              },
              "quantity": {
                "$ref": "#/components/schemas/QuantitySpec"
              },
              "quantities": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "integer"
                },
                "description": "Same as quantity.suggested (kept for compatibility)."
              }
            }
          }
        ]
      },
      "LineInput": {
        "type": "object",
        "required": [
          "quantity"
        ],
        "description": "Either resellerSku, or productId + options. options may only contain the customer option keys from GET /products/{id}; omitted options get the product-page default. quantity is the number of pieces; for products priced by run size (quantity.pricedBy=copies) it is the run size, so do not send options.copies (if you do, it must equal quantity).",
        "properties": {
          "resellerSku": {
            "type": "string"
          },
          "productId": {
            "type": "string",
            "description": "Stable product id from GET /products. (Slugs differ per language; use the id here.)"
          },
          "options": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number"
              ]
            },
            "description": "Customer options only (see Option). Unknown or automatic keys give 422 invalid_options with the allowed keys."
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "description": "Pieces. For run-priced products this is the run (copies)."
          },
          "fileUrl": {
            "type": "string",
            "format": "uri",
            "description": "Public https URL of a print-ready PDF, PNG or JPG, or EPS/AI/PS/SVG when the URL ends in that extension (converted to PDF by us before production). Checked by content at order time; other formats give 422. Required when the reseller product has no file."
          }
        }
      },
      "Recipient": {
        "type": "object",
        "required": [
          "name",
          "address1",
          "postalCode",
          "city",
          "country"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "description": "Recommended. Given to the carrier for delivery notifications. Without it the carrier gets your account email (see carrierContact)."
          },
          "phone": {
            "type": "string",
            "description": "Recommended. Given to the carrier. Without it the carrier gets your account phone number."
          },
          "address1": {
            "type": "string"
          },
          "address2": {
            "type": "string"
          },
          "postalCode": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "description": "ISO-2"
          }
        }
      },
      "Quote": {
        "type": "object",
        "properties": {
          "lines": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "productId": {
                  "type": "string"
                },
                "productName": {
                  "type": "string"
                },
                "options": {
                  "type": "object",
                  "description": "The customer options used, including defaults filled in for you. Safe to send back unchanged in POST /orders."
                },
                "quantity": {
                  "type": "integer"
                },
                "retailNetCents": {
                  "type": "integer"
                },
                "netCents": {
                  "type": "integer"
                },
                "resellerProductId": {
                  "type": "string"
                },
                "derivedOptions": {
                  "type": "object",
                  "description": "Read-only: options set automatically (e.g. printingmethod). Do not send these back."
                },
                "unitNetPrice": {
                  "type": "string",
                  "description": "netCents / quantity in euro as a decimal string, not rounded to cents (e.g. \"0.0944\"). netCents is authoritative."
                }
              }
            }
          },
          "discountPercent": {
            "type": "number"
          },
          "subtotalNetCents": {
            "type": "integer"
          },
          "shippingNetCents": {
            "type": "integer"
          },
          "vatRate": {
            "type": "number"
          },
          "vatTreatment": {
            "type": "string"
          },
          "vatCents": {
            "type": "integer"
          },
          "totalCents": {
            "type": "integer"
          },
          "currency": {
            "const": "EUR"
          }
        }
      },
      "OrderInput": {
        "type": "object",
        "required": [
          "lines",
          "recipient"
        ],
        "properties": {
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LineInput"
            }
          },
          "recipient": {
            "$ref": "#/components/schemas/Recipient"
          },
          "externalOrderId": {
            "type": "string"
          },
          "externalOrderNumber": {
            "type": "string"
          },
          "reference": {
            "type": "string",
            "description": "Your reference, shown on the invoice"
          }
        }
      },
      "OrderResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "resellerOrderId": {
            "type": "string"
          },
          "orderNumber": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "AWAITING_FUNDS",
              "AWAITING_FILE",
              "PAYMENT_FAILED",
              "SUBMITTED",
              "CANCELLED"
            ]
          },
          "totalCents": {
            "type": "integer"
          },
          "chargedCents": {
            "type": "integer"
          },
          "duplicate": {
            "type": "boolean"
          },
          "test": {
            "type": "boolean"
          },
          "failureReason": {
            "type": "string"
          },
          "carrierContact": {
            "type": "object",
            "properties": {
              "emailSource": {
                "type": "string",
                "enum": [
                  "recipient",
                  "reseller"
                ]
              },
              "phoneSource": {
                "type": "string",
                "enum": [
                  "recipient",
                  "reseller"
                ]
              }
            }
          }
        }
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "resellerOrderId": {
            "type": "string"
          },
          "orderNumber": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "AWAITING_FUNDS",
              "AWAITING_FILE",
              "PAYMENT_FAILED",
              "SUBMITTED",
              "CANCELLED"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PAID",
              "PROCESSING",
              "PRINTING",
              "SHIPPED",
              "DELIVERED",
              "CANCELLED",
              "REFUNDED"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "API",
              "DASHBOARD",
              "SHOPIFY",
              "WOOCOMMERCE",
              "ETSY",
              "WIX",
              "TIKTOK_SHOP",
              "AMAZON"
            ]
          },
          "test": {
            "type": "boolean"
          },
          "idempotencyKey": {
            "type": "string"
          },
          "externalOrderId": {
            "type": [
              "string",
              "null"
            ]
          },
          "externalOrderNumber": {
            "type": [
              "string",
              "null"
            ]
          },
          "paymentMode": {
            "type": "string",
            "enum": [
              "WALLET",
              "CARD_ON_SUBMIT"
            ]
          },
          "failureReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "totals": {
            "type": "object",
            "properties": {
              "currency": {
                "const": "EUR"
              },
              "subtotalCents": {
                "type": "integer"
              },
              "shippingCents": {
                "type": "integer"
              },
              "discountCents": {
                "type": "integer",
                "description": "Your reseller discount on the retail price, excl. VAT (sum of items[].discountCents)."
              },
              "vatCents": {
                "type": "integer"
              },
              "totalCents": {
                "type": "integer"
              },
              "chargedCents": {
                "type": "integer"
              },
              "discountIncludesVat": {
                "const": false
              }
            }
          },
          "tracking": {
            "type": "object",
            "properties": {
              "code": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "recipient": {
            "$ref": "#/components/schemas/Recipient"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "productId": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "quantity": {
                  "type": "integer"
                },
                "options": {
                  "type": "object"
                },
                "fileUrl": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "unitPriceCents": {
                  "type": "integer",
                  "description": "Rounded to whole cents; use totalPriceCents (authoritative) or unitPrice."
                },
                "totalPriceCents": {
                  "type": "integer"
                },
                "unitPrice": {
                  "type": "string",
                  "description": "totalPriceCents / quantity in euro as an unrounded decimal string (incl. VAT as charged)."
                },
                "retailNetCents": {
                  "type": "integer"
                },
                "netCents": {
                  "type": "integer"
                },
                "discountCents": {
                  "type": "integer",
                  "description": "retailNetCents - netCents (excl. VAT)."
                }
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "submittedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "shippedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "deliveredAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "cancelledAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "carrierContact": {
            "type": "object",
            "description": "Contact details the carrier receives for delivery messages. When the recipient has no email/phone, your reseller account contact is used, so the carrier contacts you instead of the end customer.",
            "properties": {
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "emailSource": {
                "type": "string",
                "enum": [
                  "recipient",
                  "reseller"
                ]
              },
              "phoneSource": {
                "type": "string",
                "enum": [
                  "recipient",
                  "reseller"
                ]
              }
            }
          }
        }
      },
      "ResellerProductInput": {
        "type": "object",
        "required": [
          "productId",
          "sku",
          "title"
        ],
        "properties": {
          "productId": {
            "type": "string"
          },
          "sku": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "options": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number"
              ]
            }
          },
          "fileUrl": {
            "type": "string",
            "format": "uri"
          },
          "mockupUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "retailPriceCents": {
            "type": "integer"
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "ResellerProductPatch": {
        "type": "object",
        "properties": {
          "sku": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "options": {
            "type": "object"
          },
          "fileUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "mockupUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "retailPriceCents": {
            "type": [
              "integer",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "ResellerProduct": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "productId": {
            "type": "string"
          },
          "sku": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "options": {
            "type": "object"
          },
          "fileUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "mockupUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "retailPriceCents": {
            "type": [
              "integer",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "allEvents": {
            "type": "boolean"
          },
          "active": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Deterministic event id; dedupe on it"
          },
          "type": {
            "type": "string",
            "enum": [
              "order.created",
              "order.submitted",
              "order.awaiting_funds",
              "order.payment_failed",
              "order.in_production",
              "order.shipped",
              "order.delivered",
              "order.cancelled",
              "order.file_problem"
            ]
          },
          "created": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "properties": {
              "order": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "orderNumber": {
                    "type": "string"
                  },
                  "externalOrderId": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "externalOrderNumber": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "state": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string"
                  },
                  "tracking": {
                    "type": "object",
                    "properties": {
                      "code": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "url": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "productId": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "quantity": {
                          "type": "integer"
                        },
                        "options": {
                          "type": "object"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "ErrorDetail": {
        "type": "object",
        "description": "One problem in the request. `line` is the 0-based line index, `field` the option key (or quantity, fileUrl, productId, resellerSku).",
        "properties": {
          "line": {
            "type": "integer"
          },
          "field": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "unknown_option",
              "invalid_value",
              "not_a_number",
              "out_of_range",
              "conflict",
              "quantity_mismatch",
              "quantity_unavailable",
              "not_available",
              "unknown_product",
              "product_unavailable",
              "unknown_sku",
              "invalid_url",
              "file_unreachable",
              "file_format_not_accepted",
              "file_url_not_allowed"
            ]
          },
          "message": {
            "type": "string"
          },
          "allowedValues": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "allowedKeys": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "min": {
            "type": "number"
          },
          "max": {
            "type": "number"
          },
          "nearest": {
            "type": "integer",
            "description": "quantity_unavailable: nearest run size that can be priced."
          },
          "suggested": {
            "type": "string",
            "description": "conflict after pricing: the value our print partner would use."
          },
          "detected": {
            "type": "string",
            "description": "file_format_not_accepted: detected file type (e.g. ico)."
          },
          "accepted": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "QuantitySpec": {
        "type": "object",
        "description": "pricedBy=copies: the price depends on the run size; send the run as the line quantity (25000 flyers = quantity 25000). pricedBy=units: price per piece/tier.",
        "properties": {
          "pricedBy": {
            "type": "string",
            "enum": [
              "copies",
              "units"
            ]
          },
          "min": {
            "type": [
              "integer",
              "null"
            ]
          },
          "max": {
            "type": [
              "integer",
              "null"
            ]
          },
          "suggested": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          }
        }
      }
    },
    "headers": {
      "RateLimit-Limit": {
        "description": "Requests allowed in the current window for the strictest limit that applies to this call (per key per minute, or an account budget).",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Remaining": {
        "description": "Requests left in that window.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Reset": {
        "description": "Seconds until that window resets.",
        "schema": {
          "type": "integer"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying (on 429).",
        "schema": {
          "type": "integer"
        }
      }
    }
  }
}