{
  "components": {
    "schemas": {
      "ChangedRow": {
        "additionalProperties": false,
        "description": "A movement whose re-sent id replaced one of another type, or another product's.",
        "properties": {
          "field": {
            "description": "What the replaced movement had differently: its `type` (a sale replaced by a return, say), or its `sku`.",
            "enum": [
              "type",
              "sku"
            ],
            "type": "string"
          },
          "row": {
            "description": "The row, counted from 0.",
            "type": "integer"
          }
        },
        "required": [
          "row",
          "field"
        ],
        "type": "object"
      },
      "CompleteSnapshotRequest": {
        "additionalProperties": false,
        "description": "Without it, completing refuses to deactivate more than half the active items.",
        "properties": {
          "allow_large_deactivation": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "Completion": {
        "additionalProperties": false,
        "properties": {
          "dry_run": {
            "type": "boolean"
          },
          "large_deactivation": {
            "type": "boolean"
          },
          "result": {
            "$ref": "#/components/schemas/SnapshotResult"
          },
          "status": {
            "enum": [
              "open",
              "completed"
            ],
            "type": "string"
          }
        },
        "required": [
          "dry_run",
          "status",
          "large_deactivation",
          "result"
        ],
        "type": "object"
      },
      "DraftOrderLine": {
        "additionalProperties": false,
        "description": "One line of a pushed draft.\n\nThe item by its `sku`, as items and movements are, or by Verity's `item`\nid; one of the two. `quantity` left out is not zero: it is \"no quantity\ndecided yet\", which a draft line is allowed to be. Sending it as null is\nrefused, like every other null here.",
        "properties": {
          "item": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer"
          },
          "quantity": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer"
          },
          "sku": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          }
        },
        "type": "object"
      },
      "DraftOrderRequest": {
        "additionalProperties": false,
        "properties": {
          "lines": {
            "items": {
              "$ref": "#/components/schemas/DraftOrderLine"
            },
            "maxItems": 5000,
            "minItems": 1,
            "type": "array"
          },
          "notes": {
            "maxLength": 2000,
            "minLength": 1,
            "type": "string"
          },
          "supplier": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer"
          }
        },
        "required": [
          "supplier"
        ],
        "type": "object"
      },
      "Error": {
        "additionalProperties": false,
        "properties": {
          "detail": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        },
        "required": [
          "detail"
        ],
        "type": "object"
      },
      "ErrorDetail": {
        "additionalProperties": true,
        "properties": {
          "detail": {
            "type": "string"
          },
          "errors": {
            "items": {
              "$ref": "#/components/schemas/Problem"
            },
            "type": "array"
          },
          "errors_total": {
            "type": "integer"
          },
          "kind": {
            "type": "string"
          }
        },
        "required": [
          "detail",
          "kind",
          "errors",
          "errors_total"
        ],
        "type": "object"
      },
      "ItemRow": {
        "additionalProperties": false,
        "description": "One item, by SKU. A field left out is left as it is. An item Verity does\nnot have yet must carry name and quantity_on_hand.",
        "properties": {
          "barcode": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "category": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "clear": {
            "items": {
              "enum": [
                "unit_cost",
                "unit_price",
                "reorder_point",
                "reorder_qty",
                "lead_time_days",
                "variant",
                "category",
                "supplier",
                "barcode",
                "location",
                "supplier_sku",
                "supplier_price"
              ],
              "type": "string"
            },
            "maxItems": 32,
            "type": "array"
          },
          "is_active": {
            "type": "boolean"
          },
          "lead_time_days": {
            "maximum": 365,
            "minimum": 0,
            "type": "integer"
          },
          "location": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "name": {
            "maxLength": 255,
            "minLength": 1,
            "type": "string"
          },
          "quantity_on_hand": {
            "maximum": 2147483647,
            "minimum": -2147483648,
            "type": "integer"
          },
          "reorder_point": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer"
          },
          "reorder_qty": {
            "maximum": 1000000000,
            "minimum": 1,
            "type": "integer"
          },
          "sku": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "supplier": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "supplier_price": {
            "description": "At most 6 decimal places.",
            "maximum": 1000000000000.0,
            "minimum": 0,
            "type": "number"
          },
          "supplier_sku": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "unit_cost": {
            "description": "At most 6 decimal places.",
            "maximum": 1000000000000.0,
            "minimum": 0,
            "type": "number"
          },
          "unit_price": {
            "description": "At most 6 decimal places.",
            "maximum": 1000000000000.0,
            "minimum": 0,
            "type": "number"
          },
          "variant": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "sku"
        ],
        "type": "object"
      },
      "ItemsRequest": {
        "additionalProperties": false,
        "properties": {
          "currency": {
            "pattern": "^[A-Z]{3}$",
            "type": "string"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/ItemRow"
            },
            "maxItems": 5000,
            "minItems": 1,
            "type": "array"
          },
          "observed_at": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "observed_at",
          "items"
        ],
        "type": "object"
      },
      "ItemsResult": {
        "additionalProperties": false,
        "properties": {
          "created": {
            "type": "integer"
          },
          "dry_run": {
            "type": "boolean"
          },
          "placeholder_suppliers": {
            "description": "Rows whose supplier was text meaning nobody — \"N/A\", \"TBD\", \"unknown\" and the like — so no supplier was set: the item keeps the one it had.",
            "type": "integer"
          },
          "rows": {
            "type": "integer"
          },
          "stale": {
            "type": "integer"
          },
          "updated": {
            "type": "integer"
          }
        },
        "required": [
          "dry_run",
          "rows",
          "created",
          "updated",
          "stale",
          "placeholder_suppliers"
        ],
        "type": "object"
      },
      "KeyDisplay": {
        "additionalProperties": false,
        "properties": {
          "display": {
            "type": "string"
          }
        },
        "required": [
          "display"
        ],
        "type": "object"
      },
      "MinimumOrder": {
        "additionalProperties": false,
        "description": "Where an order stands against its supplier's minimum order value — a warning,\nnever a refusal: an order below it can still be sent. Amounts are exact digits\nin the supplier's currency, never converted. `met`: the priced lines already\nreach it. `below`: every line has a quantity and a price, and the order is\nshort by `short_by`. `may_be_below`: short on the lines that have both, with\n`unpriced_lines` that could make it up. `other_currency`: the order is in\nanother currency than the minimum, and is not compared.",
        "properties": {
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "minimum": {
            "type": "string"
          },
          "priced_lines": {
            "type": "integer"
          },
          "short_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "state": {
            "enum": [
              "met",
              "below",
              "may_be_below",
              "other_currency"
            ],
            "type": "string"
          },
          "unpriced_lines": {
            "type": "integer"
          },
          "value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "state",
          "minimum",
          "currency",
          "value",
          "short_by",
          "priced_lines",
          "unpriced_lines"
        ],
        "type": "object"
      },
      "MovementRow": {
        "additionalProperties": false,
        "description": "One sale, receipt, return or adjustment. Sending the same id again replaces\nthat movement. A quantity is a positive whole number, except an adjustment's,\nwhose sign is its direction: positive into stock, negative out of it. A sale\nor a return may name its channel, where it came through; a receipt or an\nadjustment has none.",
        "properties": {
          "channel": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "id": {
            "maxLength": 124,
            "minLength": 1,
            "type": "string"
          },
          "moved_at": {
            "format": "date-time",
            "type": "string"
          },
          "quantity": {
            "maximum": 2147483647,
            "minimum": -2147483647,
            "type": "integer"
          },
          "sku": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "type": {
            "enum": [
              "sale",
              "receipt",
              "return",
              "adjustment"
            ],
            "type": "string"
          },
          "unit_price": {
            "description": "At most 6 decimal places.",
            "maximum": 1000000000000.0,
            "minimum": 0,
            "type": "number"
          }
        },
        "required": [
          "id",
          "sku",
          "type",
          "quantity",
          "moved_at"
        ],
        "type": "object"
      },
      "MovementsRequest": {
        "additionalProperties": false,
        "properties": {
          "currency": {
            "pattern": "^[A-Z]{3}$",
            "type": "string"
          },
          "movements": {
            "items": {
              "$ref": "#/components/schemas/MovementRow"
            },
            "maxItems": 5000,
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "movements"
        ],
        "type": "object"
      },
      "MovementsResult": {
        "additionalProperties": false,
        "properties": {
          "changed": {
            "description": "Rows whose `id` was already a movement of another type, or another item's, which the row then replaced. Empty when no re-sent id changed what it was. A return needs an id of its own: given its sale's, it replaces the sale.",
            "items": {
              "$ref": "#/components/schemas/ChangedRow"
            },
            "type": "array"
          },
          "created": {
            "type": "integer"
          },
          "dry_run": {
            "type": "boolean"
          },
          "rows": {
            "type": "integer"
          },
          "updated": {
            "type": "integer"
          }
        },
        "required": [
          "dry_run",
          "rows",
          "created",
          "updated",
          "changed"
        ],
        "type": "object"
      },
      "OpenSnapshotRequest": {
        "additionalProperties": false,
        "description": "When the sender began reading the catalogue it is about to send.",
        "properties": {
          "observed_at": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "observed_at"
        ],
        "type": "object"
      },
      "Ping": {
        "additionalProperties": false,
        "properties": {
          "api_version": {
            "const": "v1",
            "type": "string"
          },
          "key": {
            "$ref": "#/components/schemas/KeyDisplay"
          },
          "limits": {
            "$ref": "#/components/schemas/PingLimits"
          },
          "workspace": {
            "$ref": "#/components/schemas/PingWorkspace"
          }
        },
        "required": [
          "api_version",
          "key",
          "workspace",
          "limits"
        ],
        "type": "object"
      },
      "PingLimits": {
        "additionalProperties": false,
        "properties": {
          "max_body_bytes": {
            "type": "integer"
          },
          "requests_per_minute": {
            "type": "integer"
          },
          "rows_per_day": {
            "type": "integer"
          },
          "rows_per_request": {
            "type": "integer"
          }
        },
        "required": [
          "requests_per_minute",
          "max_body_bytes",
          "rows_per_request",
          "rows_per_day"
        ],
        "type": "object"
      },
      "PingWorkspace": {
        "additionalProperties": false,
        "properties": {
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "timezone": {
            "type": "string"
          }
        },
        "required": [
          "currency",
          "timezone"
        ],
        "type": "object"
      },
      "Problem": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "enum": [
              "both-given",
              "currency-mismatch",
              "currency-not-set",
              "duplicate-id",
              "duplicate-sku",
              "empty",
              "invalid",
              "invalid-character",
              "invalid-timestamp",
              "invalid-value",
              "listed-twice",
              "not-clearable",
              "not-for-type",
              "null-not-allowed",
              "out-of-range",
              "required",
              "required-to-create",
              "set-and-cleared",
              "surrounding-whitespace",
              "timestamp-needs-offset",
              "too-early",
              "too-far-in-future",
              "too-long",
              "too-many-decimals",
              "too-many-rows",
              "unknown-field",
              "unknown-sku",
              "wrong-type"
            ],
            "type": "string"
          },
          "field": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "row": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "row",
          "field",
          "code"
        ],
        "type": "object"
      },
      "PurchaseOrder": {
        "additionalProperties": false,
        "properties": {
          "closed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string"
          },
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "expected_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "type": "integer"
          },
          "line_count": {
            "type": "integer"
          },
          "lines": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/PurchaseOrderLine"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ]
          },
          "minimum_order": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/MinimumOrder"
              },
              {
                "type": "null"
              }
            ]
          },
          "number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sent_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string"
          },
          "supplier": {
            "type": "integer"
          },
          "supplier_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "units": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "number",
          "status",
          "supplier",
          "supplier_name",
          "currency",
          "created_at",
          "sent_at",
          "expected_at",
          "closed_at",
          "minimum_order",
          "line_count",
          "units"
        ],
        "type": "object"
      },
      "PurchaseOrderLine": {
        "additionalProperties": false,
        "description": "One line of an order. `quantity` is null on a draft line nobody has decided yet.",
        "properties": {
          "id": {
            "type": "integer"
          },
          "item": {
            "type": "integer"
          },
          "quantity": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "received": {
            "type": "integer"
          },
          "sku": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "unit_price": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "item",
          "sku",
          "quantity",
          "received",
          "unit_price"
        ],
        "type": "object"
      },
      "PurchaseOrderList": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "type": "integer"
          },
          "purchase_orders": {
            "items": {
              "$ref": "#/components/schemas/PurchaseOrder"
            },
            "type": "array"
          },
          "rows": {
            "type": "integer"
          }
        },
        "required": [
          "purchase_orders",
          "rows",
          "limit"
        ],
        "type": "object"
      },
      "ReceiptLine": {
        "additionalProperties": false,
        "description": "One line of a delivery: the order line it is against, and how many came.",
        "properties": {
          "line": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer"
          },
          "quantity": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer"
          }
        },
        "required": [
          "line",
          "quantity"
        ],
        "type": "object"
      },
      "ReceiptRequest": {
        "additionalProperties": false,
        "properties": {
          "add_to_stock": {
            "type": "boolean"
          },
          "id": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "lines": {
            "items": {
              "$ref": "#/components/schemas/ReceiptLine"
            },
            "maxItems": 5000,
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "lines"
        ],
        "type": "object"
      },
      "ReceiptResult": {
        "additionalProperties": false,
        "description": "What a pushed delivery did. `repeated` means this `id` had already arrived.",
        "properties": {
          "movements": {
            "type": "integer"
          },
          "receipt": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "repeated": {
            "type": "boolean"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "receipt",
          "repeated",
          "status",
          "movements"
        ],
        "type": "object"
      },
      "Snapshot": {
        "additionalProperties": false,
        "properties": {
          "expires_at": {
            "format": "date-time",
            "type": "string"
          },
          "finished_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "type": "string"
          },
          "observed_at": {
            "format": "date-time",
            "type": "string"
          },
          "opened_at": {
            "format": "date-time",
            "type": "string"
          },
          "pages": {
            "type": "integer"
          },
          "result": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapshotResult"
              },
              {
                "type": "null"
              }
            ]
          },
          "rows": {
            "type": "integer"
          },
          "status": {
            "enum": [
              "open",
              "completed",
              "abandoned",
              "expired"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "observed_at",
          "opened_at",
          "expires_at",
          "finished_at",
          "pages",
          "rows",
          "result"
        ],
        "type": "object"
      },
      "SnapshotPageRequest": {
        "additionalProperties": false,
        "properties": {
          "currency": {
            "pattern": "^[A-Z]{3}$",
            "type": "string"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/ItemRow"
            },
            "maxItems": 5000,
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "items"
        ],
        "type": "object"
      },
      "SnapshotResult": {
        "additionalProperties": false,
        "properties": {
          "active_before": {
            "type": "integer"
          },
          "deactivated": {
            "type": "integer"
          },
          "deactivated_with_stock": {
            "type": "integer"
          }
        },
        "required": [
          "active_before",
          "deactivated",
          "deactivated_with_stock"
        ],
        "type": "object"
      },
      "Supplier": {
        "additionalProperties": false,
        "properties": {
          "address_line1": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "address_line2": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "contacts": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/SupplierContact"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ]
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "type": "integer"
          },
          "is_active": {
            "type": "boolean"
          },
          "lead_time_days": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "min_order_qty": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "min_order_value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "name": {
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "pack_size": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "region": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "vat_number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "external_id",
          "address_line1",
          "address_line2",
          "city",
          "postal_code",
          "region",
          "country",
          "currency",
          "vat_number",
          "lead_time_days",
          "min_order_qty",
          "min_order_value",
          "pack_size",
          "notes",
          "is_active"
        ],
        "type": "object"
      },
      "SupplierContact": {
        "additionalProperties": false,
        "description": "A person at a supplier. Only with the contacts permission.",
        "properties": {
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "type": "integer"
          },
          "is_primary": {
            "type": "boolean"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "phone",
          "role",
          "is_primary"
        ],
        "type": "object"
      },
      "SupplierList": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "rows": {
            "type": "integer"
          },
          "suppliers": {
            "items": {
              "$ref": "#/components/schemas/Supplier"
            },
            "type": "array"
          }
        },
        "required": [
          "suppliers",
          "rows",
          "limit",
          "offset"
        ],
        "type": "object"
      },
      "SupplierRow": {
        "additionalProperties": false,
        "description": "One supplier, by `id` (the sender's own) or by name.\n\nA field left out is left as it is; a field in `clear` is emptied. The NAME is\nnever changed by a push: which spelling a supplier goes by is the merchant's\ndecision, made on the Suppliers page (phase 1.1). A row whose name is not\nknown yet CREATES that supplier.",
        "properties": {
          "address_line1": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "address_line2": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "city": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "clear": {
            "items": {
              "enum": [
                "address_line1",
                "address_line2",
                "city",
                "postal_code",
                "region",
                "country",
                "currency",
                "vat_number",
                "lead_time_days",
                "min_order_qty",
                "min_order_value",
                "pack_size",
                "notes"
              ],
              "type": "string"
            },
            "maxItems": 32,
            "type": "array"
          },
          "country": {
            "pattern": "^[A-Za-z]{2}$",
            "type": "string"
          },
          "currency": {
            "pattern": "^[A-Z]{3}$",
            "type": "string"
          },
          "id": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          },
          "lead_time_days": {
            "maximum": 365,
            "minimum": 0,
            "type": "integer"
          },
          "min_order_qty": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer"
          },
          "min_order_value": {
            "description": "At most 6 decimal places.",
            "maximum": 1000000000000.0,
            "minimum": 0,
            "type": "number"
          },
          "name": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "notes": {
            "maxLength": 4000,
            "minLength": 1,
            "type": "string"
          },
          "pack_size": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer"
          },
          "postal_code": {
            "maxLength": 16,
            "minLength": 1,
            "type": "string"
          },
          "region": {
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "vat_number": {
            "maxLength": 32,
            "minLength": 1,
            "type": "string"
          }
        },
        "type": "object"
      },
      "SuppliersRequest": {
        "additionalProperties": false,
        "properties": {
          "currency": {
            "pattern": "^[A-Z]{3}$",
            "type": "string"
          },
          "suppliers": {
            "items": {
              "$ref": "#/components/schemas/SupplierRow"
            },
            "maxItems": 5000,
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "suppliers"
        ],
        "type": "object"
      },
      "SuppliersResult": {
        "additionalProperties": false,
        "properties": {
          "created": {
            "type": "integer"
          },
          "dry_run": {
            "type": "boolean"
          },
          "rows": {
            "type": "integer"
          },
          "updated": {
            "type": "integer"
          }
        },
        "required": [
          "dry_run",
          "rows",
          "created",
          "updated"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "apiKey": {
        "description": "Send `Authorization: Bearer <key>` with a key made in Verity under Account settings → API keys. Call from a server: a request from a web page is refused.",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "Send your stock data to Verity from your own systems. Send `Authorization: Bearer <key>` with a key made in Verity under Account settings → API keys. Call from a server: a request from a web page is refused.",
    "title": "Verity API",
    "version": "1"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/items": {
      "post": {
        "description": "Fields sent are set; fields left out are kept; fields named in `clear` are removed, and `null` is refused. An item Verity does not have yet needs `name` and `quantity_on_hand`. An item already held as observed later than `observed_at` is left as it is and counted as `stale`. A supplier named by text that means nobody (\"N/A\", \"TBD\") is not set, and counted as `placeholder_suppliers`. All or nothing.",
        "operationId": "pushItems",
        "parameters": [
          {
            "description": "Make every check a real request makes and answer what it would do, writing nothing.",
            "in": "query",
            "name": "dry_run",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ItemsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemsResult"
                }
              }
            },
            "description": "Written — or, with `dry_run`, what would be."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Create or update items, by SKU",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/movements": {
      "post": {
        "description": "Each movement carries your own `id`; sending an id again replaces that movement, so a retry never counts a sale twice. A return is a movement of its own and needs an id of its own: sent with its sale's, it replaces the sale, and `changed` lists the row. Every `sku` must already be an item. A movement does not change `quantity_on_hand`. All or nothing.",
        "operationId": "pushMovements",
        "parameters": [
          {
            "description": "Make every check a real request makes and answer what it would do, writing nothing.",
            "in": "query",
            "name": "dry_run",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MovementsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MovementsResult"
                }
              }
            },
            "description": "Written — or, with `dry_run`, what would be."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Record sales and receipts",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/ping": {
      "get": {
        "description": "Which key this is, the workspace's currency and timezone, and the limits. Carries no business data.",
        "operationId": "ping",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ping"
                }
              }
            },
            "description": "The key is accepted."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Check a key",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/purchase-orders": {
      "get": {
        "description": "What has been ordered and where each order stands, newest first. NEEDS THE PURCHASING PERMISSION, like every other read of what a merchant buys; a key without it is refused (`forbidden`). `lines` is null here — ask for one order to see them.",
        "operationId": "listPurchaseOrders",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 20,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          {
            "in": "query",
            "name": "supplier",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maximum": 2147483647,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 500,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurchaseOrderList"
                }
              }
            },
            "description": "The orders."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Your purchase orders",
        "tags": [
          "v1"
        ]
      },
      "post": {
        "description": "A DRAFT, AND ONLY A DRAFT. Taking a number and sending an order to a supplier is a person's decision, made in Verity — a key that could send would turn a bug in a script into a real order at a real company. Send `lines` to say what you want ordered; leave them out entirely and Verity suggests what the workspace needs. NEEDS THE PURCHASING PERMISSION, though it writes: the answer carries the supplier's prices, your costs and, when Verity fills it in, quantities from your sales — a key without it is refused (`forbidden`). A rule that refuses the draft answers `purchasing-refused`.",
        "operationId": "draftPurchaseOrder",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DraftOrderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurchaseOrder"
                }
              }
            },
            "description": "The draft, with its lines."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Start a draft order",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/purchase-orders/{order_id}": {
      "get": {
        "description": "As `listPurchaseOrders`, for one order, and `lines` carries the items, quantities and prices. Same permission.",
        "operationId": "getPurchaseOrder",
        "parameters": [
          {
            "in": "path",
            "name": "order_id",
            "required": true,
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurchaseOrder"
                }
              }
            },
            "description": "The order."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "One order, with its lines",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/purchase-orders/{order_id}/receipts": {
      "post": {
        "description": "A delivery against a sent order, line by line. `add_to_stock` is false unless you say otherwise — a system that counts stock of its own would be double-counted, and this cannot know which one yours is. Send your own `id` and a retry is safe: the same delivery twice is one, answered with `repeated: true`. An order whose status has no room for a delivery is refused with `conflict`.",
        "operationId": "pushReceipt",
        "parameters": [
          {
            "in": "path",
            "name": "order_id",
            "required": true,
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceiptRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReceiptResult"
                }
              }
            },
            "description": "What the delivery did."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Record what arrived",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/snapshots": {
      "post": {
        "description": "`observed_at` is when you began reading the catalogue you are about to send. One snapshot may be open per workspace, for 24 hours.",
        "operationId": "openSnapshot",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OpenSnapshotRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            },
            "description": "Opened."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Open a full-catalogue snapshot",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/snapshots/{snapshot_id}": {
      "delete": {
        "description": "Nothing is deactivated. Pages already sent stay written.",
        "operationId": "abandonSnapshot",
        "parameters": [
          {
            "description": "The id `openSnapshot` answered with.",
            "in": "path",
            "name": "snapshot_id",
            "required": true,
            "schema": {
              "pattern": "^[0-9a-f]{32}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            },
            "description": "Abandoned."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Abandon a snapshot",
        "tags": [
          "v1"
        ]
      },
      "get": {
        "description": "Its status, the pages and rows sent, and what completing it did.",
        "operationId": "getSnapshot",
        "parameters": [
          {
            "description": "The id `openSnapshot` answered with.",
            "in": "path",
            "name": "snapshot_id",
            "required": true,
            "schema": {
              "pattern": "^[0-9a-f]{32}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            },
            "description": "The snapshot."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "How a snapshot stands",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/snapshots/{snapshot_id}/complete": {
      "post": {
        "description": "Every active item no page listed, and no push observed after the snapshot's `observed_at`, is marked inactive — never deleted. Refused (`large-deactivation`, 409, with the counts) when more than half of the active items would go, unless `allow_large_deactivation` is true. Completing a completed snapshot answers the same again.",
        "operationId": "completeSnapshot",
        "parameters": [
          {
            "description": "The id `openSnapshot` answered with.",
            "in": "path",
            "name": "snapshot_id",
            "required": true,
            "schema": {
              "pattern": "^[0-9a-f]{32}$",
              "type": "string"
            }
          },
          {
            "description": "Make every check a real request makes and answer what it would do, writing nothing.",
            "in": "query",
            "name": "dry_run",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompleteSnapshotRequest"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Completion"
                }
              }
            },
            "description": "Completed — or, with `dry_run`, what would be."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Complete a snapshot",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/snapshots/{snapshot_id}/items": {
      "post": {
        "description": "An items push observed at the snapshot's `observed_at`, which also marks every item it lists as seen, and active again unless the row sends `is_active: false`. A SKU may be on several pages, once per page.",
        "operationId": "pushSnapshotPage",
        "parameters": [
          {
            "description": "The id `openSnapshot` answered with.",
            "in": "path",
            "name": "snapshot_id",
            "required": true,
            "schema": {
              "pattern": "^[0-9a-f]{32}$",
              "type": "string"
            }
          },
          {
            "description": "Make every check a real request makes and answer what it would do, writing nothing.",
            "in": "query",
            "name": "dry_run",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SnapshotPageRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemsResult"
                }
              }
            },
            "description": "Written — or, with `dry_run`, what would be."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Send one page of a snapshot",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/suppliers": {
      "get": {
        "description": "Companies and their terms. NEEDS THE PURCHASING PERMISSION, chosen when the key is made; a key without it is refused (`forbidden`), and an existing key never gains one. `contacts=true` also needs the CONTACTS permission: those are the people at a supplier, they are personal data, and every read of them is recorded with counts.",
        "operationId": "listSuppliers",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 200,
              "maximum": 500,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "contacts",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupplierList"
                }
              }
            },
            "description": "The suppliers."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Your suppliers, and what they charge",
        "tags": [
          "v1"
        ]
      },
      "post": {
        "description": "Each row carries your own `id`, the supplier's `name`, or both. A row is matched by your id first, then by the name however it is spelled; one that matches nothing creates a supplier and needs a `name`. The NAME OF AN EXISTING SUPPLIER IS NEVER CHANGED by a push — which spelling it goes by is the merchant's decision, made in Verity. Fields named in `clear` are emptied. All or nothing. Needs no read permission.",
        "operationId": "pushSuppliers",
        "parameters": [
          {
            "description": "Make every check a real request makes and answer what it would do, writing nothing.",
            "in": "query",
            "name": "dry_run",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SuppliersRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuppliersResult"
                }
              }
            },
            "description": "Written — or, with `dry_run`, what would be."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "Create or update suppliers, by your id or their name",
        "tags": [
          "v1"
        ]
      }
    },
    "/api/v1/suppliers/{supplier_id}": {
      "get": {
        "description": "As `listSuppliers`, for one supplier. Same two permissions.",
        "operationId": "getSupplier",
        "parameters": [
          {
            "in": "path",
            "name": "supplier_id",
            "required": true,
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "contacts",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Supplier"
                }
              }
            },
            "description": "The supplier."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is not JSON (`invalid-json`), or its length header is not a number."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or a key that is not accepted — the same answer whatever the reason."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Sent from a web browser (`browser-origin`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No such path, or a snapshot that is not this key's (`no-such-snapshot`)."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something else is writing to the workspace (`workspace-busy`), or a snapshot or purchase order is in the wrong state for this (`conflict`)."
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is larger than one request may be (`body-too-large`)."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The body is compressed, or not sent as `application/json`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request has problems (`invalid-request`), listed in `errors` by row, field and code — or a rule of purchasing refuses it (`purchasing-refused`). Nothing was written."
          },
          "423": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The account is scheduled for deletion."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Too many requests this minute (`rate-limited`) or rows today (`daily-row-limit`). See `Retry-After`."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Something unexpected; nothing reported as written. Quote the X-Request-ID header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The workspace's tables are being updated (`workspace-updating`), or the database could not be reached. Nothing was written; retry after Retry-After."
          }
        },
        "summary": "One supplier",
        "tags": [
          "v1"
        ]
      }
    }
  },
  "security": [
    {
      "apiKey": []
    }
  ],
  "servers": [
    {
      "url": "https://useverityapp.com"
    }
  ]
}
