{
  "openapi": "3.1.0",
  "info": {
    "title": "Superroute Platform Apps — partner surface",
    "version": "1.0.0",
    "description": "Apps that third parties build for a service provider's customers or drivers. Served on the Open Platform host under /app. Tokens issued here are accepted nowhere else, and no other Superroute credential is accepted here. See the GraphQL twin in partner-app-graphql-docs.json."
  },
  "servers": [
    {
      "url": "https://open.superroute.ca"
    }
  ],
  "components": {
    "securitySchemes": {
      "partnerAppToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "A partner app access token (sp_app_…) from /app/oauth/token."
      },
      "partnerAppKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-App-Key",
        "description": "A restricted app key (sp_appkey_…) for calls before sign-in. Not a secret: it names one approved partner app; a browser must send it from one of the app's registered web origins."
      }
    },
    "schemas": {
      "OAuthError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "error_description": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string",
            "example": "sp_app_01jbx….…"
          },
          "token_type": {
            "type": "string",
            "example": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "example": 3600
          },
          "refresh_token": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "example": "orders.shipping tracking"
          }
        },
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "refresh_token",
          "scope"
        ]
      },
      "PlatformAppEmailChallenge": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "challenge_id": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "description": "Masked."
          },
          "expires_in": {
            "type": "integer",
            "description": "Seconds."
          },
          "resend_after": {
            "type": "integer",
            "description": "Seconds."
          }
        }
      },
      "OrderPictureDelete": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 123
          }
        }
      },
      "PlatformAppGuestRates": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "rates": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "rate_id": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "self_delivery",
                    "label_service"
                  ]
                },
                "shipping_price": {
                  "type": "string"
                },
                "currency": {
                  "type": "string"
                },
                "carrier_name": {
                  "type": "string"
                },
                "service_name": {
                  "type": "string"
                },
                "transit_days": {
                  "type": "integer"
                }
              }
            }
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "PlatformAppGuestVerifyRequested": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "challenge_id": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "phone"
            ]
          },
          "contact": {
            "type": "string",
            "description": "Masked."
          },
          "expires_in": {
            "type": "integer",
            "description": "Seconds."
          },
          "resend_after": {
            "type": "integer",
            "description": "Seconds."
          }
        }
      },
      "OrderNotesSave": {
        "type": "object",
        "properties": {
          "orderId": {
            "$ref": "#/components/schemas/orderId"
          },
          "notes": {
            "type": "string",
            "example": "this is an example"
          }
        }
      },
      "PlatformAppGuestOrderList": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlatformAppGuestOrder"
            }
          }
        }
      },
      "PlatformAppGuestClients": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "app": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              },
              "count": {
                "type": "integer"
              },
              "items": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "client_code": {
                      "type": "string"
                    },
                    "display_name": {
                      "type": "string"
                    },
                    "logo_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "primary_color": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "features": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "quotes",
                          "shipping"
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "PlatformAppQuoteAnswer": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "quote": {
            "type": "object",
            "description": "Present when the shipment is covered. token is what an order carries as quote_token.",
            "additionalProperties": true,
            "properties": {
              "line": {
                "type": "string"
              },
              "currency": {
                "type": "string"
              },
              "total": {
                "type": "number"
              },
              "token": {
                "type": "string"
              },
              "valid_until": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "earliest_delivery_date": {
                "type": "string",
                "format": "date",
                "description": "Only on delivery and express quotes from one of the client's warehouses while the client has schedule-based transport planning on: the earliest delivery day by its lane departures, in the client's time zone. An estimate, not a promise; absent otherwise."
              },
              "drive_minutes": {
                "type": "integer",
                "minimum": 1,
                "description": "Only while the client shows driving times (Customer Portal settings, off by default) on a delivery, pickup or express quote that starts at one of the line's listed locations: the driving time by car, in whole minutes rounded up, from the chosen location or, when none was chosen, from the nearest listed location. Absent otherwise, including for a typed starting point or when the time cannot be worked out.",
                "example": 18
              },
              "drive_from": {
                "type": "string",
                "description": "Present together with drive_minutes: the name of the location the driving time is measured from, as listed in the quote schema's origins.",
                "example": "Toronto Depot"
              }
            }
          },
          "not_covered_reason": {
            "type": "string",
            "description": "Present when result is false."
          }
        }
      },
      "ValidateRefOrderId": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "integer",
            "example": 123
          },
          "ref": {
            "type": "string",
            "example": "abc"
          }
        }
      },
      "RouteStatusUpdate": {
        "type": "object",
        "properties": {
          "routeId": {
            "type": "integer",
            "example": 123
          },
          "gps_tracking_id": {
            "type": "integer",
            "example": 123
          }
        }
      },
      "PlatformAppGuestOrderAnswer": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "guest_order": {
            "$ref": "#/components/schemas/PlatformAppGuestOrder"
          }
        }
      },
      "OrderRateV3": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "example": "D",
            "required": false,
            "description": "Order Type: D:delivery (default), P:Pickup, P2P:Peer to Peer. For a pickup the sender is the pickup stop and the recipient is where the parcel goes."
          },
          "from_address": {
            "type": "string",
            "example": "1010 Rue Sainte-Catherine O",
            "required": true,
            "description": "Sender street line."
          },
          "from_address_2": {
            "type": [
              "string",
              "null"
            ],
            "example": null,
            "required": false,
            "description": "Sender second address line (unit, suite). Optional."
          },
          "from_city": {
            "type": "string",
            "example": "Montréal",
            "required": true,
            "description": "Sender city."
          },
          "from_province": {
            "type": "string",
            "example": "QC",
            "required": true,
            "description": "Sender province/state."
          },
          "from_country": {
            "type": "string",
            "example": "CA",
            "required": true,
            "description": "Sender country."
          },
          "from_postcode": {
            "type": "string",
            "example": "H3B 1G1",
            "required": true,
            "description": "Sender postcode."
          },
          "to_address": {
            "type": "string",
            "example": "6841 Rue Saint-Denis",
            "required": true,
            "description": "Recipient street line."
          },
          "to_address_2": {
            "type": [
              "string",
              "null"
            ],
            "example": null,
            "required": false,
            "description": "Recipient second address line (unit, suite). Optional."
          },
          "to_city": {
            "type": "string",
            "example": "Montréal",
            "required": true,
            "description": "Recipient city."
          },
          "to_province": {
            "type": "string",
            "example": "QC",
            "required": true,
            "description": "Recipient province/state."
          },
          "to_country": {
            "type": "string",
            "example": "CA",
            "required": true,
            "description": "Recipient country."
          },
          "to_postcode": {
            "type": "string",
            "example": "H2S 2S3",
            "required": true,
            "description": "Recipient postcode."
          },
          "packages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "weight": {
                  "type": "number",
                  "example": 1.234,
                  "description": "Weight of the package in weight_unit."
                },
                "width": {
                  "type": "number",
                  "example": 10.532,
                  "description": "Width of the package in dimension_unit.",
                  "pattern": "^[0-9]+(\\.[0-9]{1,3})?$"
                },
                "height": {
                  "type": "number",
                  "example": 20.332,
                  "description": "Height of the package in dimension_unit.",
                  "pattern": "^[0-9]+(\\.[0-9]{1,3})?$"
                },
                "length": {
                  "type": "number",
                  "example": 15.232,
                  "description": "Length of the package in dimension_unit.",
                  "pattern": "^[0-9]+(\\.[0-9]{1,3})?$"
                },
                "dimension_unit": {
                  "type": "integer",
                  "enum": [
                    1,
                    2,
                    3,
                    4
                  ],
                  "description": "Unit for the dimensions. 1: mm, 2: cm, 3: m, 4: inch",
                  "example": 1,
                  "default": 1
                },
                "weight_unit": {
                  "type": "integer",
                  "enum": [
                    1,
                    2,
                    3,
                    4
                  ],
                  "description": "Unit for the weight. 1: g, 2: kg, 3: oz, 4: lb",
                  "example": 1,
                  "default": 1
                }
              },
              "required": [
                "weight",
                "width",
                "height",
                "length"
              ]
            }
          },
          "signature_option": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "description": "Indicates if a signature is required. 0: No signature, 1: Signature required.",
            "example": 0,
            "default": 0
          },
          "channel_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The ID of the channel. Optional. Must be one of the business's own channels (otherwise 400); the channel's pricing unit and rules apply.",
            "example": null,
            "default": null
          },
          "fulfillment_center_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The ID of the fulfillment center. Default is null.",
            "example": null,
            "default": null
          },
          "customer_id": {
            "type": [
              "integer",
              "null"
            ],
            "example": null,
            "required": false,
            "description": "Client and employee callers only: the customer (users id) the shipment is quoted for, so the quote is priced on that customer's plan — the plan the order would be charged under. Must be one of the business's customers (otherwise 400). A customer caller is always quoted as itself. Optional."
          },
          "customer_code": {
            "type": [
              "string",
              "null"
            ],
            "example": null,
            "required": false,
            "description": "Client and employee callers only: the customer by customer code, used when customer_id is not given. Optional."
          },
          "time_window_start": {
            "type": [
              "string",
              "null"
            ],
            "example": "2026-10-01 09:00:00",
            "required": false,
            "description": "Delivery window start, Y-m-d H:i:s. Optional."
          },
          "time_window_end": {
            "type": [
              "string",
              "null"
            ],
            "example": "2026-10-01 13:00:00",
            "required": false,
            "description": "Delivery window end, Y-m-d H:i:s, not before time_window_start. Optional. The self_delivery price may depend on the window."
          },
          "quote_labels": {
            "type": "boolean",
            "example": false,
            "default": false,
            "required": false,
            "description": "Also quote the caller's label carrier accounts, all at once. Default false. When true, from_name, from_telephone, to_name and to_telephone are required, and every service of every account is added to rates with type label_service."
          },
          "shipping_methods": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer"
            },
            "example": null,
            "required": false,
            "description": "Label accounts (shipping method ids) to quote when quote_labels is true. Optional; default every active account the caller may ship with (a combo account is left out of the default set). An id the caller may not use is refused (400)."
          },
          "carriers": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "example": null,
            "required": false,
            "description": "Restrict the label quote to these carriers. Optional."
          },
          "services": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "example": null,
            "required": false,
            "description": "Restrict the label quote to these services. Optional."
          },
          "from_name": {
            "type": [
              "string",
              "null"
            ],
            "example": "Sender Co",
            "required": false,
            "description": "Sender name. Required when quote_labels is true."
          },
          "from_telephone": {
            "type": [
              "string",
              "null"
            ],
            "example": "5145550100",
            "required": false,
            "description": "Sender telephone. Required when quote_labels is true."
          },
          "to_name": {
            "type": [
              "string",
              "null"
            ],
            "example": "Jane Doe",
            "required": false,
            "description": "Recipient name. Required when quote_labels is true."
          },
          "to_telephone": {
            "type": [
              "string",
              "null"
            ],
            "example": "5145550199",
            "required": false,
            "description": "Recipient telephone. Required when quote_labels is true."
          }
        },
        "required": [
          "from_address",
          "from_city",
          "from_province",
          "from_country",
          "from_postcode",
          "to_address",
          "to_city",
          "to_province",
          "to_country",
          "to_postcode",
          "packages"
        ]
      },
      "PlatformAppGuestOrderCreated": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "order_token": {
            "type": "string",
            "description": "Shown once. Sent as X-Guest-Order-Token to read or cancel this shipment."
          },
          "guest_order": {
            "$ref": "#/components/schemas/PlatformAppGuestOrder"
          }
        }
      },
      "PlatformAppQuoteSchema": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "schema": {
            "type": "object",
            "description": "The client's quote form: business name, currency, validity, offered lines with their origins and fields, units, call to action.",
            "additionalProperties": true
          }
        }
      },
      "PlatformAppGuestOrder": {
        "type": "object",
        "description": "A guest shipment as the guest sees it. The created order is shown only once it exists.",
        "properties": {
          "id": {
            "type": "integer"
          },
          "kind": {
            "type": "string",
            "enum": [
              "self_delivery",
              "label"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_payment",
              "paid",
              "placing",
              "placed",
              "cancelling",
              "expired",
              "cancelled",
              "refunded",
              "refund_required"
            ]
          },
          "amount": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "contact": {
            "type": "string",
            "description": "The verified contact, masked."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "pay_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "pay_before": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "can_cancel": {
            "type": "boolean"
          },
          "order": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "ref": {
                "type": "string"
              },
              "status_group": {
                "type": "string"
              },
              "status_label": {
                "type": "string"
              },
              "packages": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "tracking_number": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "OrderPictureUpload": {
        "type": "object",
        "properties": {
          "orderId": {
            "$ref": "#/components/schemas/orderId"
          },
          "type": {
            "type": "string",
            "example": "photo"
          },
          "image": {
            "type": "string",
            "example": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXN"
          },
          "imageUrl": {
            "type": "string",
            "example": "http://abc.com/a.png"
          },
          "gps_tracking_id": {
            "type": "integer",
            "example": null
          },
          "operation_event_id": {
            "type": "integer",
            "example": null
          },
          "tracking_event_id": {
            "type": "integer",
            "example": null,
            "description": "Optional. The tracking event the proof documents (a delivered / picked-up / failed-attempt event of this order). When omitted it is derived from operation_event_id, or from the order's latest outcome event; a proof uploaded before the outcome is reported is tied to that outcome when the driver reports it."
          }
        }
      },
      "orderId": {
        "type": "integer",
        "example": 12345
      },
      "OptimizeRouteForDriver": {
        "type": "object",
        "properties": {
          "async": {
            "type": "boolean",
            "example": true,
            "default": true
          },
          "routeId": {
            "type": "integer",
            "example": 123,
            "description": "The ID of the route to assign drivers to"
          },
          "driverAddresses": {
            "type": "object",
            "description": "Optional per-driver address info",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "start_address_id": {
                  "type": "integer",
                  "nullable": true,
                  "example": 1001
                },
                "start_address": {
                  "type": "object",
                  "nullable": true,
                  "properties": {
                    "name": {
                      "type": "string",
                      "example": "Warehouse A"
                    },
                    "lat": {
                      "type": "number",
                      "example": 43.65107
                    },
                    "lng": {
                      "type": "number",
                      "example": -79.347015
                    },
                    "address_1": {
                      "type": "string",
                      "example": "123 Main St"
                    },
                    "city": {
                      "type": "string",
                      "example": "Toronto"
                    },
                    "province": {
                      "type": "string",
                      "example": "ON"
                    },
                    "country": {
                      "type": "string",
                      "example": "CA"
                    },
                    "postcode": {
                      "type": "string",
                      "example": "M5V2T6"
                    }
                  }
                },
                "end_address_id": {
                  "type": "integer",
                  "nullable": true,
                  "example": 1002
                },
                "end_address": {
                  "type": "object",
                  "nullable": true,
                  "properties": {
                    "name": {
                      "type": "string",
                      "example": "Dropoff Point Z"
                    },
                    "lat": {
                      "type": "number",
                      "example": 43.70011
                    },
                    "lng": {
                      "type": "number",
                      "example": -79.4163
                    },
                    "address_1": {
                      "type": "string",
                      "example": "456 King St"
                    },
                    "city": {
                      "type": "string",
                      "example": "Toronto"
                    },
                    "province": {
                      "type": "string",
                      "example": "ON"
                    },
                    "country": {
                      "type": "string",
                      "example": "CA"
                    },
                    "postcode": {
                      "type": "string",
                      "example": "M5V1K1"
                    }
                  }
                }
              }
            },
            "example": {
              "start_address_id": 1001,
              "start_address": {
                "name": "Warehouse A",
                "lat": 43.65107,
                "lng": -79.347015
              },
              "end_address_id": 1002,
              "end_address": {
                "name": "Dropoff Point Z",
                "address_1": "456 King St",
                "city": "Toronto",
                "province": "ON",
                "country": "CA",
                "postcode": "M5V1K1"
              }
            }
          }
        },
        "required": [
          "routeId"
        ]
      },
      "OrderStatusUpdate": {
        "type": "object",
        "properties": {
          "orderId": {
            "$ref": "#/components/schemas/orderId"
          },
          "packageIds": {
            "type": "array",
            "example": [
              1,
              2,
              3
            ]
          },
          "status": {
            "type": "string",
            "example": "NR"
          },
          "return_reason_id": {
            "type": "integer",
            "example": 1
          },
          "gps_tracking_id": {
            "type": "integer",
            "example": 1
          },
          "routeId": {
            "type": "integer",
            "example": 123
          },
          "delivery_pin": {
            "type": "string",
            "description": "6-digit delivery PIN code for proof of delivery verification",
            "minLength": 6,
            "maxLength": 6,
            "example": "123456"
          }
        }
      },
      "OrderCreateV3": {
        "type": "object",
        "required": [
          "rate_id",
          "from_address",
          "from_city",
          "from_province",
          "from_country",
          "from_postcode",
          "to_address",
          "to_city",
          "to_province",
          "to_country",
          "to_postcode",
          "to_name",
          "packages"
        ],
        "properties": {
          "rate_id": {
            "type": "string",
            "example": "eyJpdiI6Ik1rT2Z...",
            "required": true,
            "description": "A rate_id from POST /v1/uniorder/rate. Decides the service (self_delivery or label_service), and for a self delivery the customer and channel, for a label the account, carrier and service. Valid for 30 minutes, for the caller it was issued to only."
          },
          "from_address": {
            "type": "string",
            "example": "1010 Rue Sainte-Catherine O",
            "required": true,
            "description": "Sender street line."
          },
          "from_address_2": {
            "type": [
              "string",
              "null"
            ],
            "example": "Suite 400",
            "required": false,
            "description": "Sender second address line (unit, suite)."
          },
          "from_city": {
            "type": "string",
            "example": "Montréal",
            "required": true,
            "description": "Sender city."
          },
          "from_province": {
            "type": "string",
            "example": "QC",
            "required": true,
            "description": "Sender province/state."
          },
          "from_country": {
            "type": "string",
            "example": "CA",
            "required": true,
            "description": "Sender country."
          },
          "from_postcode": {
            "type": "string",
            "example": "H3B 1G1",
            "required": true,
            "description": "Sender postcode."
          },
          "from_name": {
            "type": [
              "string",
              "null"
            ],
            "example": "Sender Co",
            "required": false,
            "description": "Sender name. Required for a label_service rate and for type P."
          },
          "from_company_name": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Sender company."
          },
          "from_telephone": {
            "type": [
              "string",
              "null"
            ],
            "example": "5145550100",
            "required": false,
            "description": "Sender telephone. Required for a label_service rate."
          },
          "from_email": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Sender email."
          },
          "from_buzz_code": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Sender buzz code."
          },
          "to_address": {
            "type": "string",
            "example": "6841 Rue Saint-Denis",
            "required": true,
            "description": "Recipient street line."
          },
          "to_address_2": {
            "type": [
              "string",
              "null"
            ],
            "example": "Apt 2",
            "required": false,
            "description": "Recipient second address line (unit, suite)."
          },
          "to_city": {
            "type": "string",
            "example": "Montréal",
            "required": true,
            "description": "Recipient city."
          },
          "to_province": {
            "type": "string",
            "example": "QC",
            "required": true,
            "description": "Recipient province/state."
          },
          "to_country": {
            "type": "string",
            "example": "CA",
            "required": true,
            "description": "Recipient country."
          },
          "to_postcode": {
            "type": "string",
            "example": "H2S 2S3",
            "required": true,
            "description": "Recipient postcode."
          },
          "to_name": {
            "type": "string",
            "example": "Jane Doe",
            "required": true,
            "description": "Recipient name."
          },
          "to_company_name": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Recipient company."
          },
          "to_telephone": {
            "type": [
              "string",
              "null"
            ],
            "example": "5145550199",
            "required": false,
            "description": "Recipient telephone. Required for a label_service rate."
          },
          "to_email": {
            "type": [
              "string",
              "null"
            ],
            "example": "jane@example.com",
            "required": false,
            "description": "Recipient email."
          },
          "to_buzz_code": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Recipient buzz code."
          },
          "packages": {
            "type": "array",
            "required": true,
            "description": "Packages, in the shape the quote took; weight is required. ref, external_tracking_number, package_value, insurance_value and (label_service) items are kept on the order.",
            "items": {
              "type": "object",
              "properties": {
                "weight": {
                  "type": "number"
                },
                "length": {
                  "type": "number"
                },
                "width": {
                  "type": "number"
                },
                "height": {
                  "type": "number"
                },
                "dimension_unit": {
                  "type": "integer"
                },
                "weight_unit": {
                  "type": "integer"
                },
                "ref": {
                  "type": "string"
                },
                "external_tracking_number": {
                  "type": "string"
                },
                "package_value": {
                  "type": "number"
                },
                "insurance_value": {
                  "type": "number"
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            },
            "example": [
              {
                "weight": 2.5,
                "weight_unit": 2,
                "length": 30,
                "width": 20,
                "height": 15,
                "dimension_unit": 2,
                "ref": "PKG-1"
              }
            ]
          },
          "type": {
            "type": [
              "string",
              "null"
            ],
            "example": "D",
            "required": false,
            "description": "Order type: D (delivery, default), P (pickup: the sender is the pickup stop), P2P. A label_service rate takes D only."
          },
          "ref": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Order reference."
          },
          "order_code": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Order code (max 5 letters and numbers)."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Note."
          },
          "quote_token": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "maxLength": 64,
            "description": "Optional. The token of the public quote (/quotes) this order comes from. Once the order is created the quote records it; an unknown or already converted token is ignored and never fails the order."
          },
          "notification_language": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Notification language."
          },
          "signature_option": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "0: no signature, 1: signature required."
          },
          "insurance_option": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "Insurance option."
          },
          "auto_deduplication": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "Refuse an order whose ref or package ref already exists (0/1)."
          },
          "shipping_from": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "Address book id of the sender, instead of the from_* address, where the account or the order needs one."
          },
          "shipping_from_code": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Address book unique identifier of the sender, when shipping_from is not given."
          },
          "order_batch": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "Order batch."
          },
          "pickup_instruction": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Pickup instruction."
          },
          "delivery_instruction": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Delivery instruction."
          },
          "need_pick_up": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. 0 no, 1 yes (the parcel is collected at the sender), 2 inbound scan, 3 batch pickup."
          },
          "allow_dropoff": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Allow dropoff (0/1)."
          },
          "pin_verification_required": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. PIN verification required (0/1)."
          },
          "self_pickup": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Self pickup (0/1)."
          },
          "strict_duplicate_check": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Strict duplicate check (0/1)."
          },
          "service_time": {
            "type": [
              "number",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Service time in seconds."
          },
          "pickup_service_time": {
            "type": [
              "number",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Pickup service time in seconds."
          },
          "pickup_date": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Pickup date (Y-m-d)."
          },
          "schedule_date": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Schedule date (Y-m-d)."
          },
          "time_window_start": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Delivery window start (Y-m-d H:i:s)."
          },
          "time_window_end": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Delivery window end (Y-m-d H:i:s)."
          },
          "pickup_time_window_start": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Pickup window start (Y-m-d H:i:s)."
          },
          "pickup_time_window_end": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Pickup window end (Y-m-d H:i:s)."
          },
          "tip_amount": {
            "type": [
              "number",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Tip amount."
          },
          "skills": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Required skills (comma-separated skill ids)."
          },
          "fulfillment_center_code": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. Fulfillment center code."
          },
          "surcharges": {
            "type": [
              "array",
              "null"
            ],
            "required": false,
            "description": "self_delivery only. [{code, selected_values}].",
            "items": {
              "type": "object"
            }
          },
          "external_order_id": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "label_service only. External order id."
          },
          "export_reason": {
            "type": [
              "integer",
              "null"
            ],
            "required": false,
            "description": "label_service only. Export reason."
          },
          "package_type": {
            "type": [
              "string",
              "null"
            ],
            "required": false,
            "description": "label_service only. Package type of the account."
          }
        }
      },
      "CustomerOrderFormField": {
        "type": "object",
        "description": "One field of a custom form bound to storage, moving or shipping orders.",
        "properties": {
          "code": {
            "type": "string",
            "description": "The key the answer is sent under in form_data."
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "textarea",
              "checkbox",
              "select",
              "multiselect",
              "datetime",
              "daterange",
              "file"
            ],
            "description": "checkbox with options = several choices (list of values); checkbox without options = a yes / no box (\"1\"); multiselect = list of values; daterange = {start, end}."
          },
          "required": {
            "type": "boolean"
          },
          "display_name": {
            "type": "object",
            "description": "Label per language code.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "options": {
            "type": "array",
            "description": "The choices, resolved from the field's source (manual list, dataset or base codes); the server accepts only these values.",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "display_name": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "default_value": {
            "description": "Initial value as the back office set it."
          },
          "sort_order": {
            "type": "integer"
          },
          "format": {
            "type": "string",
            "description": "datetime / daterange only: YYYY-MM-DD (a date), HH:mm or HH:mm:ss (a time), or a format with both (date and time). Empty for other types.",
            "example": "YYYY-MM-DD"
          },
          "min_value": {
            "type": "string",
            "description": "datetime / daterange only: the earliest value accepted by the picker. Empty when not set."
          },
          "max_value": {
            "type": "string",
            "description": "datetime / daterange only: the latest value accepted by the picker. Empty when not set."
          }
        }
      },
      "PlatformAppGuestContactToken": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "contact_token": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "phone"
            ]
          },
          "contact": {
            "type": "string",
            "description": "Masked."
          },
          "expires_in": {
            "type": "integer",
            "description": "Seconds."
          }
        }
      },
      "PlatformAppGuestLabel": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "format": {
            "type": "string",
            "enum": [
              "pdf"
            ]
          },
          "tracking_numbers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pdf_data": {
            "type": "string",
            "description": "Base64 PDF."
          }
        }
      }
    }
  },
  "paths": {
    "/app/v1/health": {
      "get": {
        "x-route-name": "openapp.health",
        "tags": [
          "Surface"
        ],
        "summary": "Surface status",
        "description": "Public. Liveness and where the GraphQL endpoint and documentation are.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "request_id": "req_01…",
                  "status": "ok",
                  "service": "Superroute Platform Apps",
                  "surface": "partner",
                  "version": "v1",
                  "graphql": "/app/graphql",
                  "documentation": "/developer/app",
                  "time": "2026-10-28T12:00:00-04:00"
                }
              }
            }
          }
        },
        "operationId": "health"
      }
    },
    "/app/oauth/authorize": {
      "get": {
        "x-route-name": "openapp.oauth.authorize",
        "tags": [
          "OAuth"
        ],
        "summary": "Sign-in page",
        "description": "Authorization code flow with PKCE (RFC 6749 §4.1, RFC 7636). Opens the Superroute sign-in page, branded as the service provider. Errors before the app and its redirect URI are verified are shown on the page; later errors are sent back to the redirect URI.",
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The partner app's code (p_…)."
            }
          },
          {
            "name": "client_code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The service provider's public client code for this app."
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "One of the app's registered redirect URIs, exactly."
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Returned unchanged; up to 500 characters."
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "BASE64URL(SHA-256(code_verifier))."
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            }
          },
          {
            "name": "ui_locales",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "en, chs, cht, de, es, fr, it, nl, pt, sr, hu, pl, sk or cs."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The sign-in page (HTML)."
          },
          "302": {
            "description": "Back to the redirect URI with error and state."
          },
          "400": {
            "description": "The app, client code or redirect URI is not valid (HTML)."
          }
        }
      },
      "post": {
        "x-route-name": "openapp.oauth.sign_in",
        "tags": [
          "OAuth"
        ],
        "summary": "Sign-in page form",
        "description": "Posted by the sign-in page itself, not by apps. On success redirects to the redirect URI with code and state; the code is valid for 60 seconds and once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "request": {
                    "type": "string",
                    "description": "The sealed request from the page."
                  },
                  "email": {
                    "type": "string",
                    "description": ""
                  },
                  "password": {
                    "type": "string",
                    "description": ""
                  },
                  "allow[]": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Sensitive capabilities the person ticked."
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "deny"
                    ]
                  }
                },
                "required": [
                  "request"
                ]
              }
            }
          }
        },
        "responses": {
          "302": {
            "description": "Back to the redirect URI with code and state, or with error=access_denied."
          },
          "200": {
            "description": "The second step of two-step verification (HTML)."
          },
          "401": {
            "description": "The sign-in page again with an error (HTML)."
          }
        }
      }
    },
    "/app/oauth/authorize/verify": {
      "post": {
        "x-route-name": "openapp.oauth.two_factor",
        "tags": [
          "OAuth"
        ],
        "summary": "Sign-in page second step",
        "description": "Posted by the sign-in page itself.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "request": {
                    "type": "string",
                    "description": ""
                  },
                  "code": {
                    "type": "string",
                    "description": ""
                  }
                },
                "required": [
                  "request",
                  "code"
                ]
              }
            }
          }
        },
        "responses": {
          "302": {
            "description": "Back to the redirect URI with code and state."
          },
          "401": {
            "description": "The second step again with an error (HTML)."
          }
        }
      }
    },
    "/app/oauth/token": {
      "post": {
        "x-route-name": "openapp.oauth.token",
        "tags": [
          "OAuth"
        ],
        "summary": "Tokens",
        "description": "authorization_code (with the PKCE code_verifier), refresh_token (single use: a reused refresh token revokes every token of its family) or password (only for apps approved for in-app sign-in; an account with two-step verification is answered interaction_required). or urn:ietf:params:oauth:grant-type:token-exchange (RFC 8693) for in-app Google / Apple sign-in: subject_token is the Google or Apple ID token, subject_token_type urn:ietf:params:oauth:token-type:id_token. The token must be issued for one of the Google / Apple audiences registered for the app and the app needs auth.google / auth.apple; the person is found at the serving client only (Google by its account or verified email, Apple by verified email) and nothing is linked to the account. Access tokens last 3600 seconds, refresh tokens 30 days. Public clients: no client secret.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token",
                      "password",
                      "urn:ietf:params:oauth:grant-type:token-exchange"
                    ]
                  },
                  "client_id": {
                    "type": "string",
                    "description": ""
                  },
                  "code": {
                    "type": "string",
                    "description": ""
                  },
                  "redirect_uri": {
                    "type": "string",
                    "description": ""
                  },
                  "code_verifier": {
                    "type": "string",
                    "description": ""
                  },
                  "refresh_token": {
                    "type": "string",
                    "description": ""
                  },
                  "client_code": {
                    "type": "string",
                    "description": "password and token-exchange grants"
                  },
                  "username": {
                    "type": "string",
                    "description": "password grant"
                  },
                  "password": {
                    "type": "string",
                    "description": "password grant"
                  },
                  "scope": {
                    "type": "string",
                    "description": "password and token-exchange grants: sensitive capabilities the app's own screen asked about, space-separated"
                  },
                  "device_id": {
                    "type": "string",
                    "description": ""
                  },
                  "subject_token": {
                    "type": "string",
                    "description": "token-exchange grant: the Google or Apple ID token"
                  },
                  "subject_token_type": {
                    "type": "string",
                    "enum": [
                      "urn:ietf:params:oauth:token-type:id_token"
                    ],
                    "description": "token-exchange grant"
                  }
                },
                "required": [
                  "grant_type",
                  "client_id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tokens",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "invalid_grant, invalid_request, unauthorized_client, unsupported_grant_type, interaction_required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "invalid_client or access_denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/app/oauth/revoke": {
      "post": {
        "x-route-name": "openapp.oauth.revoke",
        "tags": [
          "OAuth"
        ],
        "summary": "Revoke",
        "description": "RFC 7009. Revokes the token and every token of its family. Answered the same whether or not the token existed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_id": {
                    "type": "string",
                    "description": ""
                  },
                  "token": {
                    "type": "string",
                    "description": ""
                  }
                },
                "required": [
                  "client_id",
                  "token"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Always",
            "content": {
              "application/json": {
                "example": {}
              }
            }
          }
        }
      }
    },
    "/app/v1/me": {
      "get": {
        "x-route-name": "openapp.me",
        "x-graphql": "partnerAppMe",
        "tags": [
          "Account"
        ],
        "summary": "Who the token speaks for",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "request_id": "req_01…",
                  "app": {
                    "code": "p_acme_parcels",
                    "audience": "customer"
                  },
                  "client_code": "AB12CD34",
                  "user": {
                    "id": 700,
                    "name": "Customer"
                  },
                  "scopes": [
                    "orders.shipping",
                    "tracking"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "operationId": "partnerAppMe"
      }
    },
    "/app/graphql": {
      "post": {
        "x-route-name": "openapp.graphql",
        "tags": [
          "GraphQL"
        ],
        "summary": "GraphQL",
        "description": "The partner schema. Signed-in operations take a partner app access token, public operations a restricted app key (X-App-Key); the same answers as REST.",
        "security": [
          {
            "partnerAppToken": []
          },
          {
            "partnerAppKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "query": {
                    "type": "string"
                  },
                  "variables": {
                    "type": "object"
                  }
                },
                "required": [
                  "query"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "GraphQL response"
          },
          "401": {
            "description": "invalid_token"
          }
        }
      }
    },
    "/app/v1/wallet": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get the app-scoped customer wallet",
        "description": "Returns the selected Client's existing customer balance, credit allowance, remaining credit, available spending amount, online-payment policy and tax mode. This endpoint does not maintain a separate App balance. Needs the wallet.balance capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppWallet",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Existing Superroute customer wallet summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result",
                    "data"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "currency": "CAD",
                    "balance": "-25.00",
                    "credit_limit": "100.00",
                    "credit_used": "25.00",
                    "credit_remaining": "75.00",
                    "available_to_spend": "75.00",
                    "online_payment": {
                      "available": true,
                      "minimum_top_up": "1.00",
                      "maximum_top_up": "300.00"
                    },
                    "tax": {
                      "mode": "fixed_tax_zone"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry wallet.balance"
          }
        },
        "x-route-name": "openapp.wallet.show",
        "x-graphql": "platformAppWallet",
        "x-capability": "wallet.balance"
      }
    },
    "/app/v1/wallet/transactions": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List the customer wallet ledger",
        "description": "Returns Client- and customer-scoped entries from the existing transactions ledger, supplemented with matching payment metadata. Adjustments remain normal transaction entries. Needs the wallet.transactions capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppWalletTransactions",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "payment",
                "credit",
                "adjustment",
                "charge",
                "refund"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1,
                2,
                3
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated ledger",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": 501,
                        "category": "payment",
                        "amount": "50.00",
                        "balance_effect": "50.00",
                        "direction": "credit",
                        "payment": {
                          "gateway": "alphapay",
                          "method": "wechat_pay"
                        }
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "per_page": 20,
                      "total": 1
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry wallet.transactions"
          },
          "422": {
            "description": "Invalid filter or pagination"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.wallet.transactions",
        "x-graphql": "platformAppWalletTransactions",
        "x-capability": "wallet.transactions"
      }
    },
    "/app/v1/wallet/payment-methods": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List Client-approved wallet payment methods",
        "description": "Returns only configured, App-approved gateway methods and masked saved instruments. Gateway credentials and processor secrets are never exposed. `configured_methods[].supports_top_up` is true for every gateway the app can collect a top-up through: AlphaPay and GlobePay (their own webhooks) and every other configured gateway whose driver can take a purchase (Stripe, PayPal, ...), collected through the shared payment layer. Needs the wallet.payment_methods capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppWalletPaymentMethods",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configured and masked saved methods",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "configured_methods": [
                      {
                        "id": "alphapay:wechat_pay",
                        "display_name": "WeChat Pay",
                        "supports_top_up": true,
                        "maximum_amount": "300.00"
                      }
                    ],
                    "saved_methods": [
                      {
                        "id": 701,
                        "brand": "visa",
                        "last_four": "4242",
                        "is_default": true
                      }
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry wallet.payment_methods"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.wallet.payment-methods",
        "x-graphql": "platformAppWalletPaymentMethods",
        "x-capability": "wallet.payment_methods"
      }
    },
    "/app/v1/wallet/tax-preview": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Preview configured customer tax",
        "description": "Uses the Client's existing tax zones and the customer's fixed, billing-address or service-address tax mode. The preview does not write a transaction. Needs the wallet.tax capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppWalletTaxPreview",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount"
                ],
                "properties": {
                  "amount": {
                    "type": "number",
                    "format": "double",
                    "minimum": 0
                  },
                  "country": {
                    "type": "string",
                    "nullable": true
                  },
                  "province": {
                    "type": "string",
                    "nullable": true
                  },
                  "postcode": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "amount": 100,
                "country": "Canada",
                "province": "Ontario",
                "postcode": "M5V 2T6"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculated tax preview",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "subtotal": "100.00",
                    "total_tax": "13.00",
                    "total": "113.00",
                    "tax_zone_id": 20,
                    "tax_details": [
                      {
                        "name": "HST",
                        "rate": "13.000",
                        "amount": "13.00"
                      }
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry wallet.tax"
          },
          "422": {
            "description": "Invalid amount or address"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.wallet.tax-preview",
        "x-graphql": "platformAppWalletTaxPreview",
        "x-capability": "wallet.tax"
      }
    },
    "/app/v1/wallet/top-ups": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Create an idempotent customer wallet top-up",
        "description": "Creates a payment through a Client-configured gateway and returns what the app has to do next. AlphaPay and GlobePay top-ups settle through their own verified webhooks. Every other gateway the Client has configured (Stripe cards, Apple Pay and Google Pay through the Stripe native sheet, PayPal and any other configured gateway) is collected through the shared payment layer: the top-up becomes a payment request, `next_action` carries the gateway step, and the status endpoint asks the gateway when polled. The operation record provides idempotency; the credit is written to the existing payments and transactions ledger exactly once.\n\n`next_action.type` is one of: `client_secret` (open the native payment sheet with `client_secret`, `publishable_key` and `merchant_country`), `external_redirect` (open `value` in a browser or web view), `qr_code` (show `value` as a QR code), `sdk_params` or `pending`. Non-legacy gateways also return `payment_request_token` and `payment_page_url`, the same request the scan-to-pay endpoints can show and poll. Needs the wallet.top_up capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppWalletCreateTopUp",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Client-generated stable key, 16 to 100 characters",
            "schema": {
              "type": "string",
              "example": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "payment_method_id",
                  "amount"
                ],
                "properties": {
                  "payment_method_id": {
                    "type": "string",
                    "pattern": "^[a-z0-9_-]+:[a-z0-9_-]+$"
                  },
                  "amount": {
                    "type": "number",
                    "format": "double",
                    "minimum": 0.01
                  },
                  "locale": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "payment_method_id": "stripe:card",
                "amount": 50,
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Previously created operation replayed"
          },
          "201": {
            "description": "Top-up payment created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "code": "OK",
                  "message": null,
                  "data": {
                    "id": 7001,
                    "status": "pending",
                    "gateway": "stripe",
                    "payment_method": "card",
                    "amount": "50.00",
                    "currency": "CAD",
                    "external_order_id": "AP_100_20260927120000_A1B2C3",
                    "gateway_payment_id": "pi_3QxampleIntent",
                    "transaction_id": null,
                    "next_action": {
                      "type": "client_secret",
                      "client_secret": "pi_3QxampleIntent_secret_abc",
                      "publishable_key": "pk_live_example",
                      "merchant_country": "CA",
                      "payment_request_token": "9f2c41ab7d6e40518c3a0b17e5d94a26",
                      "payment_page_url": "https://admin.example.com/pay/r/9f2c41ab7d6e40518c3a0b17e5d94a26"
                    },
                    "created_at": "2026-09-27T12:00:00-04:00",
                    "updated_at": "2026-09-27T12:00:00-04:00"
                  }
                },
                "examples": {
                  "stripe_sheet": {
                    "summary": "Stripe: native payment sheet (cards, Apple Pay, Google Pay)",
                    "value": {
                      "result": true,
                      "code": "OK",
                      "message": null,
                      "data": {
                        "id": 7001,
                        "status": "pending",
                        "gateway": "stripe",
                        "payment_method": "card",
                        "amount": "50.00",
                        "currency": "CAD",
                        "external_order_id": "AP_100_20260927120000_A1B2C3",
                        "gateway_payment_id": "pi_3QxampleIntent",
                        "transaction_id": null,
                        "next_action": {
                          "type": "client_secret",
                          "client_secret": "pi_3QxampleIntent_secret_abc",
                          "publishable_key": "pk_live_example",
                          "merchant_country": "CA",
                          "payment_request_token": "9f2c41ab7d6e40518c3a0b17e5d94a26",
                          "payment_page_url": "https://admin.example.com/pay/r/9f2c41ab7d6e40518c3a0b17e5d94a26"
                        },
                        "created_at": "2026-09-27T12:00:00-04:00",
                        "updated_at": "2026-09-27T12:00:00-04:00"
                      }
                    }
                  },
                  "alphapay_legacy": {
                    "summary": "AlphaPay: legacy path, settled by the AlphaPay webhook",
                    "value": {
                      "result": true,
                      "code": "OK",
                      "message": null,
                      "data": {
                        "id": 7002,
                        "status": "pending",
                        "gateway": "alphapay",
                        "payment_method": "wechat_pay",
                        "amount": "50.00",
                        "currency": "CAD",
                        "external_order_id": "AP_100_20260927120000_D4E5F6",
                        "gateway_payment_id": "ap-order-1",
                        "transaction_id": null,
                        "next_action": {
                          "type": "external_redirect",
                          "value": "weixin://pay/7002"
                        },
                        "created_at": "2026-09-27T12:00:00-04:00",
                        "updated_at": "2026-09-27T12:00:00-04:00"
                      }
                    }
                  },
                  "paypal_redirect": {
                    "summary": "PayPal or another redirect gateway",
                    "value": {
                      "result": true,
                      "code": "OK",
                      "message": null,
                      "data": {
                        "id": 7003,
                        "status": "pending",
                        "gateway": "paypal",
                        "payment_method": "paypal_express",
                        "amount": "50.00",
                        "currency": "CAD",
                        "external_order_id": "AP_100_20260927120000_G7H8I9",
                        "gateway_payment_id": "EC-1234567890",
                        "transaction_id": null,
                        "next_action": {
                          "type": "external_redirect",
                          "value": "https://www.paypal.com/checkoutnow?token=EC-1234567890",
                          "payment_request_token": "9f2c41ab7d6e40518c3a0b17e5d94a26",
                          "payment_page_url": "https://admin.example.com/pay/r/9f2c41ab7d6e40518c3a0b17e5d94a26"
                        },
                        "created_at": "2026-09-27T12:00:00-04:00",
                        "updated_at": "2026-09-27T12:00:00-04:00"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry wallet.top_up"
          },
          "409": {
            "description": "Idempotency key reused with different input"
          },
          "422": {
            "description": "Invalid amount, method or idempotency key, or the gateway refused to start the payment (status `failed`, code `TOP_UP_CREATION_FAILED`)"
          },
          "502": {
            "description": "Payment gateway rejected the creation request"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.wallet.top-ups.create",
        "x-graphql": "platformAppWalletCreateTopUp",
        "x-capability": "wallet.top_up"
      }
    },
    "/app/v1/wallet/top-ups/{operationId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get a wallet top-up status",
        "description": "Returns the current state of a top-up operation. While the operation is pending, a poll settles it when possible: AlphaPay and GlobePay operations are matched against the payment their webhook posted; every other gateway is asked directly through its payment request (Stripe, PayPal, ...), so a lost webhook never leaves a paid top-up pending. A payment request that expired unpaid moves the operation to `failed` with an explanatory message; no credit is applied. `status` is one of `creating`, `pending`, `succeeded`, `failed`, `refunded` (credit reversed after a refund). Needs the wallet.top_up capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppWalletTopUpStatus",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "operationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 7001
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current top-up status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "code": "OK",
                  "message": null,
                  "data": {
                    "id": 7001,
                    "status": "succeeded",
                    "gateway": "stripe",
                    "payment_method": "card",
                    "amount": "50.00",
                    "currency": "CAD",
                    "external_order_id": "AP_100_20260927120000_A1B2C3",
                    "gateway_payment_id": "pi_3QxampleIntent",
                    "transaction_id": 88001,
                    "next_action": {
                      "type": "client_secret",
                      "client_secret": "pi_3QxampleIntent_secret_abc",
                      "publishable_key": "pk_live_example",
                      "merchant_country": "CA",
                      "payment_request_token": "9f2c41ab7d6e40518c3a0b17e5d94a26",
                      "payment_page_url": "https://admin.example.com/pay/r/9f2c41ab7d6e40518c3a0b17e5d94a26"
                    },
                    "created_at": "2026-09-27T12:00:00-04:00",
                    "updated_at": "2026-09-27T12:03:10-04:00"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry wallet.top_up"
          },
          "404": {
            "description": "Operation not found in this App, Client and customer context"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.wallet.top-ups.show",
        "x-graphql": "platformAppWalletTopUpStatus",
        "x-capability": "wallet.top_up"
      }
    },
    "/app/v1/privacy": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get app privacy overview",
        "description": "Returns linked global identity providers, verified-phone state, legal links, data domains and pending deletion status. account.can_request_deletion is false for an account the app must not offer to close (staff and sub-accounts, which their owner closes); the account-deletion call refuses those with ACCOUNT_DELETION_NOT_AVAILABLE. Answered exactly as the internal route.",
        "operationId": "platformAppPrivacy",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Privacy overview",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "App or Client access is not allowed"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.privacy.show",
        "x-graphql": "platformAppPrivacy"
      }
    },
    "/app/v1/privacy/account-deletion": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Request account closure",
        "description": "Opens a reviewed account closure. The account is suspended immediately — sign-in and API access both stop and every live token is revoked — and the business is notified to approve or reject it. The customer is emailed a withdrawal link, and `withdrawal_token` is returned here once so the app can offer the same withdrawal itself.\n\nBackward compatible with the previous delete-request endpoint: the response keeps its shape, `status` keeps its original values (`pending`, `cancelled`, `completed`) and gained one new value (`rejected`), and the added fields are additive. Answered exactly as the internal route.",
        "operationId": "platformAppRequestAccountDeletion",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirmation"
                ],
                "properties": {
                  "confirmation": {
                    "type": "boolean"
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              },
              "example": {
                "confirmation": true,
                "reason": "No longer using MiBox"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deletion request accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Closure request opened and the account suspended.",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "message": "Account deletion was requested and all MiBox sessions were signed out.",
                  "data": {
                    "id": 42,
                    "status": "pending",
                    "requested_at": "2026-09-05T10:00:00+00:00",
                    "cancelled_at": null,
                    "completed_at": null,
                    "handled_at": null,
                    "reason": "Moving away",
                    "decision_reason": null,
                    "requires_review": true,
                    "withdrawal_token": "one-shot-withdrawal-token"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "App or Client access is not allowed"
          },
          "422": {
            "description": "Invalid request"
          },
          "409": {
            "description": "This account cannot request closure"
          }
        },
        "x-route-name": "openapp.privacy.account-deletion.request",
        "x-graphql": "platformAppRequestAccountDeletion"
      },
      "delete": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Cancel app account deletion",
        "operationId": "platformAppCancelAccountDeletion",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Pending deletion request cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "App or Client access is not allowed"
          },
          "404": {
            "description": "Pending request not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "description": "Withdraws the pending closure request while a session still exists. Once the request has taken the session away, use POST /v1/apps/{appCode}/account-closure/withdraw with the one-shot token instead. Answered exactly as the internal route.",
        "x-route-name": "openapp.privacy.account-deletion.cancel",
        "x-graphql": "platformAppCancelAccountDeletion"
      }
    },
    "/app/v1/privacy/phone/verify": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Verify and link the signed-in customer's phone",
        "description": "Consumes the customer-bound SMS challenge, creates the shared verified phone identity and updates the customer's primary telephone. A phone linked to another global account cannot be reused. Answered exactly as the internal route.",
        "operationId": "platformAppVerifyPhone",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge_id",
                  "code"
                ],
                "properties": {
                  "challenge_id": {
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 64
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[0-9]{6}$"
                  },
                  "locale": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "challenge_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
                "code": "123456",
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Phone verified and linked",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "message": "Your phone number was verified.",
                  "data": {
                    "verified_phone": true,
                    "phone_e164": "+14****0100"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "App access or phone verification is disabled"
          },
          "409": {
            "description": "Phone linked to another account or verification is already running"
          },
          "410": {
            "description": "Verification challenge expired or belongs to another account"
          },
          "422": {
            "description": "Invalid verification code"
          },
          "429": {
            "description": "Verification attempt limit exceeded"
          }
        },
        "x-route-name": "openapp.privacy.phone.verify",
        "x-graphql": "platformAppVerifyPhone"
      }
    },
    "/app/v1/privacy/phone/request": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Request phone verification for the signed-in customer",
        "description": "Creates a five-minute challenge using the Client's existing SMS configuration. The challenge is bound to the authenticated customer, App and Client. Answered exactly as the internal route.",
        "operationId": "platformAppRequestPhoneVerification",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone"
                ],
                "properties": {
                  "phone": {
                    "type": "string",
                    "maxLength": 50
                  },
                  "locale": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "phone": "+1 416 555 0100",
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification challenge created",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "message": "A verification code was sent.",
                  "challenge_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
                  "phone_e164": "+14****0100",
                  "expires_in": 300,
                  "resend_after": 60
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "App access or phone verification is disabled"
          },
          "409": {
            "description": "The customer already has a verified phone"
          },
          "422": {
            "description": "Invalid phone number"
          },
          "429": {
            "description": "Code request rate limit exceeded"
          },
          "503": {
            "description": "Client SMS service is unavailable"
          }
        },
        "x-route-name": "openapp.privacy.phone.request",
        "x-graphql": "platformAppRequestPhoneVerification"
      }
    },
    "/app/v1/home": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "App home screen summary",
        "description": "The app home screen in one call. Each section comes from the service behind its own list endpoint and has that endpoint's shape ({\"items\": [...]}; nearby_locker is one location). pickups: ready or partly collected; returns: approved, holding a code, not dropped off; luggage: current rentals; handovers: open deals (from the deals list, under items); nearby_locker: the nearest favourite, else the nearest (origin as on locker-locations: latitude/longitude or origin_*); recent_orders: the latest orders of every type. A section is null when the Client does not run its service, and null with its code in errors when its service refused or failed; one section failing never fails the call. Answered exactly as the internal route.",
        "operationId": "platformAppHome",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "example": 45.5017
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "example": -73.5673
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Home summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "pickups": {
                      "items": [
                        {
                          "id": 72,
                          "delivery_number": "PLD-72",
                          "pickup_status": "ready",
                          "pickup_code": "482913",
                          "remaining_count": 1
                        }
                      ]
                    },
                    "returns": {
                      "items": [
                        {
                          "id": 12,
                          "status": 1,
                          "return_code": "R7K2P9",
                          "custom_channel_name": "Amazon"
                        }
                      ]
                    },
                    "luggage": null,
                    "handovers": null,
                    "nearby_locker": {
                      "id": 81,
                      "name": "Downtown locker",
                      "distance_km": 0.4,
                      "is_favorite": true
                    },
                    "recent_orders": {
                      "items": [
                        {
                          "type": "shipping",
                          "id": 710,
                          "status": "2",
                          "status_name": "Confirmed",
                          "reference": "SHIP-710"
                        }
                      ]
                    },
                    "errors": {}
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "The App, Client, role or required capability is not available"
          },
          "422": {
            "description": "Invalid origin"
          }
        },
        "x-route-name": "openapp.home",
        "x-graphql": "platformAppHome"
      }
    },
    "/app/v1/registration-details": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Registration details still to fill in",
        "description": "Unified identity: a customer a client's staff created without the registration details (the client has identity sign-in on). Until they are filled in, every other API call of the account (REST, GraphQL, MCP) answers 403 {\"error\": \"registration_incomplete\", \"code\": \"REGISTRATION_INCOMPLETE\"}; generic API logins refuse with the same body, and an app login still issues the session with registration_incomplete: true so the app can show this form. Answered exactly as the internal route.",
        "operationId": "platformAppRegistrationDetails",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Required fields, missing ones and values on file",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "complete": {
                          "type": "boolean"
                        },
                        "fields": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "missing": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "values": {
                          "type": "object"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "complete": false,
                    "fields": [
                      "name",
                      "telephone",
                      "address",
                      "city",
                      "province",
                      "postcode",
                      "country"
                    ],
                    "missing": [
                      "telephone",
                      "address"
                    ],
                    "values": {
                      "name": "Ann Lee",
                      "telephone": "",
                      "address": "",
                      "address_2": "",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H2X 1Y4",
                      "country": "Canada"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.registration-details.show",
        "x-graphql": "platformAppRegistrationDetails"
      },
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Fill in the registration details",
        "description": "Required: the fields listed by GET (province only where the client's area has provinces). Once complete, the account's API works again. Answered exactly as the internal route.",
        "operationId": "platformAppCompleteRegistration",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "telephone": "+15145550123",
                "address": "100 Rue Main"
              },
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "telephone": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string"
                  },
                  "address_2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "province": {
                    "type": "string"
                  },
                  "postcode": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved; same body as GET",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "complete": true,
                    "fields": [
                      "name",
                      "telephone",
                      "address",
                      "city",
                      "province",
                      "postcode",
                      "country"
                    ],
                    "missing": [],
                    "values": {
                      "name": "Ann Lee",
                      "telephone": "",
                      "address": "",
                      "address_2": "",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H2X 1Y4",
                      "country": "Canada"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "VALIDATION_FAILED with errors per field"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.registration-details.save",
        "x-graphql": "platformAppCompleteRegistration"
      }
    },
    "/app/v1/notifications": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List app notifications",
        "description": "Returns only database notifications scoped to the authenticated user and selected App-Client assignment. Needs the notifications.in_app capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppNotifications",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "filter",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "read",
                "unread"
              ]
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pickup",
                "orders",
                "returns",
                "wallet",
                "security"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App notification inbox",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry notifications.in_app"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.notifications.index",
        "x-graphql": "platformAppNotifications",
        "x-capability": "notifications.in_app"
      }
    },
    "/app/v1/notifications/{notificationId}/read": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mark one app notification as read",
        "operationId": "platformAppMarkNotificationRead",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "notificationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Notification marked read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry notifications.in_app"
          },
          "404": {
            "description": "Notification not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.notifications.read",
        "x-graphql": "platformAppMarkNotificationRead",
        "x-capability": "notifications.in_app",
        "description": "Needs the notifications.in_app capability on the token; answered exactly as the internal route."
      }
    },
    "/app/v1/notifications/read-all": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mark all app notifications as read",
        "operationId": "platformAppMarkAllNotificationsRead",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "All scoped notifications marked read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry notifications.in_app"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.notifications.read-all",
        "x-graphql": "platformAppMarkAllNotificationsRead",
        "x-capability": "notifications.in_app",
        "description": "Needs the notifications.in_app capability on the token; answered exactly as the internal route."
      }
    },
    "/app/v1/notifications/preferences": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get notification preferences",
        "operationId": "platformAppNotificationPreferences",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Effective Client and customer notification preferences",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "App or Client access is not allowed"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.notifications.preferences.show",
        "x-graphql": "platformAppNotificationPreferences",
        "description": "Answered exactly as the internal route."
      },
      "put": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Update notification preferences",
        "description": "Customers may opt down from the channels and categories enabled by the Client. Answered exactly as the internal route.",
        "operationId": "platformAppUpdateNotificationPreferences",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "channels",
                  "categories"
                ],
                "properties": {
                  "channels": {
                    "type": "object",
                    "required": [
                      "in_app",
                      "push",
                      "email",
                      "sms"
                    ],
                    "properties": {
                      "in_app": {
                        "type": "boolean"
                      },
                      "push": {
                        "type": "boolean"
                      },
                      "email": {
                        "type": "boolean"
                      },
                      "sms": {
                        "type": "boolean"
                      }
                    }
                  },
                  "categories": {
                    "type": "object",
                    "required": [
                      "pickup",
                      "orders",
                      "returns",
                      "wallet",
                      "security"
                    ],
                    "properties": {
                      "pickup": {
                        "type": "boolean"
                      },
                      "orders": {
                        "type": "boolean"
                      },
                      "returns": {
                        "type": "boolean"
                      },
                      "wallet": {
                        "type": "boolean"
                      },
                      "security": {
                        "type": "boolean"
                      }
                    }
                  }
                }
              },
              "example": {
                "channels": {
                  "in_app": true,
                  "push": true,
                  "email": false,
                  "sms": false
                },
                "categories": {
                  "pickup": true,
                  "orders": true,
                  "returns": true,
                  "wallet": true,
                  "security": true
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated effective preferences",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "App or Client access is not allowed"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.notifications.preferences.update",
        "x-graphql": "platformAppUpdateNotificationPreferences"
      }
    },
    "/app/v1/orders": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List app-enabled customer orders",
        "description": "Combines existing customer shipping, storage and return records into a normalized read model. It does not create a second order table or ledger. Answered exactly as the internal route.",
        "operationId": "platformAppOrders",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Order family. Each family is listed only while its capability is on for the app: shipping (orders.shipping), storage (orders.storage), return (locker.return), moving (orders.moving), delivery (orders.delivery), label (orders.label). Ships out of storage are not an order family of the app and are never listed as shipping either.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "shipping",
                "storage",
                "return",
                "moving",
                "delivery",
                "label",
                "shipout"
              ],
              "default": "all"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Existing service status",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Order ID or service-supported search term",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Unified order list. Each item keeps its type's own `status` (shipping and return: integer; storage and moving: string; delivery and label: uniorder summary string). Additive: `status_group` (pending_payment | active | completed | exception | cancelled) reads every type the same way for colouring and grouping, and `status_label` is the status name in the request language (Accept-Language). The `status` filter still matches the raw `status`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "type": "shipping",
                        "id": 710,
                        "status": 1,
                        "reference": "TRACK-001",
                        "total": "18.20",
                        "currency": "CAD",
                        "status_group": "active",
                        "status_label": "Confirmed"
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "total": 1,
                      "has_more": false
                    },
                    "creation_endpoints": {
                      "shipping_services": "/v1/customer/shipping-orders/services",
                      "storage_config": "/v1/customer/storage-orders/config"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "The App, Client, role or required capability is not available"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.orders.index",
        "x-graphql": "platformAppOrders"
      }
    },
    "/app/v1/orders/{orderType}/{orderId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Show an app-enabled customer order",
        "description": "Routes to the existing shipping, storage or return service and preserves its source-of-truth detail payload. Additive for shipping orders: `data.tracking_url`, the public tracking page (the business's own tracking domain when it has one) in the request language; null until the order has a tracking number. Additive: `wallet` — absolute Apple (.pkpass) and Google (save link) card links valid 2 h, or null when the Client has wallet cards off (docs/APP-UNIVERSAL-TRACKING-DESIGN.md UT7). Answered exactly as the internal route.",
        "operationId": "platformAppOrder",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "orderType",
            "in": "path",
            "required": true,
            "description": "The order's family as the list gives it. A shipout's detail is the one of GET /v1/customer/shipout-orders/{id}.",
            "schema": {
              "type": "string",
              "enum": [
                "shipping",
                "storage",
                "return",
                "moving",
                "delivery",
                "label",
                "shipout"
              ]
            }
          },
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "type": "shipping",
                    "order": {
                      "id": 710,
                      "tracking_number": "TRACK-001"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "The App, Client, role or required capability is not available"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.orders.show",
        "x-graphql": "platformAppOrder"
      }
    },
    "/app/v1/returns": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List customer return requests",
        "description": "Lists existing ReturnRequest records for the authenticated customer and selected Client. Needs the locker.return capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppReturns",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Existing return status",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 5
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Return requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": 901,
                        "status": 1,
                        "status_name": "Approved",
                        "return_code": "RTN-TEST",
                        "can_cancel": true,
                        "home_pickup": false
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.return"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.returns.index",
        "x-graphql": "platformAppReturns",
        "x-capability": "locker.return"
      },
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Create a customer return request",
        "description": "Creates the normal ReturnRequest record using the selected Client’s existing return channel, address, reason, approval and unique-code behavior. return_channel_id: required for self-paid and free returns; for an own label (type 3) or a return barcode (type 4) it is optional and names the platform the return is for — one of the customer's channels whose allowed_return_types include that type. With it, that channel's fee is charged and the channel decides whether a return reason and a pickup address are asked; without it, the customer's channels decide together as before. A return barcode naming a channel follows that channel: self_label_file is required, optional or ignored per its return_code_upload_mode (an own label always needs its file), reference_number is kept (and required) when the channel asks for one, and form_data answers the channel's bound form. A channel with a price charges its fee (less the best automatic promotion, or the coupon given in coupon_code) to the customer's balance in the same step; a coupon that does not apply answers 422 COUPON_INVALID and a short balance 422 INSUFFICIENT_BALANCE with errors {amount, balance, shortfall}, and nothing is created. The fee is refunded when the return is cancelled or rejected. The return carries fee: the channel fee charged when it was created ({amount, pickup_fee, discount, charged, currency, promotion_name, coupon_code, refunded, refunded_at}), or null on a free return. Whether the return waits for approval follows the channel's approval_mode (1 only free returns, 2 all, 3 none). home_pickup (optional boolean) asks for the parcel to be picked up at the pickup address: the channel must offer it (its home_pickup in the config call is not null) or the call answers 422 HOME_PICKUP_NOT_OFFERED; the pickup address (pickup_address_1, pickup_city, pickup_country, pickup_postcode) is then required whatever the channel's pickup_address_mode; when the address cannot be served the call answers 422 HOME_PICKUP_UNAVAILABLE with errors.home_pickup (the message) and errors.reason (disabled, address_required, out_of_area or not_priced). The total (the return fee after its promotion plus the pickup fee) is charged to the balance; fee.pickup_fee is the pickup part of fee.charged. Once the return is approved a pickup order is created and its id is return_order_id. The return carries home_pickup (boolean). Needs the locker.return capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppCreateReturn",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "return_type",
                  "pickup_name"
                ],
                "description": "The same rules as the customer web form. return_type 1 (self-paid) and 2 (free return, awaits approval) name a return channel (return_channel_id + return_address_id), or, for type 1 only, return_channel_id \"other\" with custom_channel_name and a typed return_name / return_address_1 / return_city / return_country / return_postcode. Type 3 (own label) uploads the label and gives self_label_channel_name plus reference_number (the label's tracking number); type 4 (return barcode) uploads a file holding exactly one barcode / QR code; neither names a channel or address. The upload is a multipart self_label_file (PDF, PNG or JPG, 10 MB) or self_label_file_base64 + self_label_file_name in JSON. pickup_address_1, pickup_city, pickup_country and pickup_postcode are required when the applicable pickup_address_mode (the channel's, other_channel's, or uploaded_label's from the config call) is 1, optional when 2, ignored when 3. reference_number is required on a channel whose reference_number_required is true. form_data answers the channel's bound form, keyed by field code. pickup_telephone and email are both optional: an empty one falls back to the account's phone / email (see contact in the config call), and the call is refused with PHONE_OR_EMAIL_REQUIRED only when neither exists. Once the return holds a return code (on creation unless it awaits approval, else on approval) the customer is emailed the code, its QR code and a link to the return's status page, in the request's language, using the Client's own \"Return Confirmation\" email template or the built-in wording; data.confirmation_email in the response is the address it goes to, or null when none is sent.",
                "properties": {
                  "original_order_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "return_type": {
                    "type": "integer",
                    "enum": [
                      1,
                      2,
                      3,
                      4
                    ],
                    "description": "1 self-paid; 2 free return requiring approval; 3 own shipping label; 4 return barcode / QR code"
                  },
                  "return_channel_id": {
                    "oneOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "string",
                        "enum": [
                          "other"
                        ]
                      }
                    ],
                    "nullable": true
                  },
                  "return_address_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "return_reason_id": {
                    "type": "integer",
                    "nullable": true,
                    "description": "required unless the applicable requires_return_reason (the channel's, other_channel's or uploaded_label's from the config call) is false, in which case it is ignored"
                  },
                  "reference_number": {
                    "type": "string",
                    "nullable": true
                  },
                  "custom_channel_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "\"other\" channel: the carrier's name"
                  },
                  "return_name": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_address_1": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_address_2": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_city": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_province": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_country": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_postcode": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_telephone": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_lat": {
                    "type": "number",
                    "nullable": true
                  },
                  "return_lng": {
                    "type": "number",
                    "nullable": true
                  },
                  "self_label_channel_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "type 3: the carrier of the uploaded label"
                  },
                  "self_label_file": {
                    "type": "string",
                    "format": "binary",
                    "nullable": true,
                    "description": "multipart upload for types 3 and 4"
                  },
                  "self_label_file_base64": {
                    "type": "string",
                    "nullable": true,
                    "description": "JSON alternative to self_label_file; bare base64 or a data URL"
                  },
                  "self_label_file_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "file name carrying the extension, with self_label_file_base64"
                  },
                  "form_data": {
                    "type": "object",
                    "additionalProperties": true,
                    "nullable": true
                  },
                  "pickup_name": {
                    "type": "string"
                  },
                  "pickup_address_1": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_address_2": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_city": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_province": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_country": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_postcode": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_lat": {
                    "type": "number",
                    "nullable": true
                  },
                  "pickup_lng": {
                    "type": "number",
                    "nullable": true
                  },
                  "pickup_telephone": {
                    "type": "string",
                    "nullable": true
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "nullable": true
                  },
                  "return_description": {
                    "type": "string",
                    "nullable": true
                  },
                  "notes": {
                    "type": "string",
                    "nullable": true
                  },
                  "coupon_code": {
                    "type": "string",
                    "maxLength": 100,
                    "nullable": true,
                    "description": "Coupon for the channel's fee (a promotion of service type return_request). Ignored on a free channel."
                  },
                  "home_pickup": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Optional. true asks for the parcel to be picked up at the pickup address, through a channel whose home_pickup (config call) is not null. pickup_address_1, pickup_city, pickup_country and pickup_postcode are then required whatever the channel's pickup_address_mode, and the pickup fee is charged with the return fee. Omitted or false keeps the previous behaviour."
                  }
                }
              },
              "examples": {
                "self_paid": {
                  "summary": "Self-paid return through a listed channel",
                  "value": {
                    "return_type": 1,
                    "return_channel_id": 4,
                    "return_address_id": 6,
                    "return_reason_id": 3,
                    "pickup_name": "MiBox Customer",
                    "pickup_address_1": "100 King Street West",
                    "pickup_city": "Toronto",
                    "pickup_province": "ON",
                    "pickup_country": "CA",
                    "pickup_postcode": "M5X 1A9",
                    "pickup_telephone": "+14165550123",
                    "return_description": "Package is unopened"
                  }
                },
                "other_channel": {
                  "summary": "Self-paid return through the \"other\" channel",
                  "value": {
                    "return_type": 1,
                    "return_channel_id": "other",
                    "custom_channel_name": "Purolator",
                    "return_reason_id": 3,
                    "return_name": "Acme Returns",
                    "return_address_1": "200 Queen Street West",
                    "return_city": "Toronto",
                    "return_province": "ON",
                    "return_country": "CA",
                    "return_postcode": "M5H 2M9",
                    "pickup_name": "MiBox Customer",
                    "pickup_address_1": "100 King Street West",
                    "pickup_city": "Toronto",
                    "pickup_province": "ON",
                    "pickup_country": "CA",
                    "pickup_postcode": "M5X 1A9",
                    "pickup_telephone": "+14165550123"
                  }
                },
                "self_label": {
                  "summary": "Own shipping label (JSON upload)",
                  "value": {
                    "return_type": 3,
                    "self_label_channel_name": "Canada Post",
                    "reference_number": "7012345678901234",
                    "return_reason_id": 3,
                    "self_label_file_name": "label.pdf",
                    "self_label_file_base64": "JVBERi0xLjQK...",
                    "pickup_name": "MiBox Customer",
                    "pickup_address_1": "100 King Street West",
                    "pickup_city": "Toronto",
                    "pickup_country": "CA",
                    "pickup_postcode": "M5X 1A9",
                    "pickup_telephone": "+14165550123"
                  }
                },
                "return_barcode": {
                  "summary": "Return barcode / QR code (JSON upload)",
                  "value": {
                    "return_type": 4,
                    "return_reason_id": 3,
                    "self_label_file_name": "return-code.png",
                    "self_label_file_base64": "iVBORw0KGgo...",
                    "pickup_name": "MiBox Customer",
                    "pickup_telephone": "+14165550123"
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "return_type",
                  "pickup_name"
                ],
                "description": "The same rules as the customer web form. return_type 1 (self-paid) and 2 (free return, awaits approval) name a return channel (return_channel_id + return_address_id), or, for type 1 only, return_channel_id \"other\" with custom_channel_name and a typed return_name / return_address_1 / return_city / return_country / return_postcode. Type 3 (own label) uploads the label and gives self_label_channel_name plus reference_number (the label's tracking number); type 4 (return barcode) uploads a file holding exactly one barcode / QR code; neither names a channel or address. The upload is a multipart self_label_file (PDF, PNG or JPG, 10 MB) or self_label_file_base64 + self_label_file_name in JSON. pickup_address_1, pickup_city, pickup_country and pickup_postcode are required when the applicable pickup_address_mode (the channel's, other_channel's, or uploaded_label's from the config call) is 1, optional when 2, ignored when 3. reference_number is required on a channel whose reference_number_required is true. form_data answers the channel's bound form, keyed by field code. pickup_telephone and email are both optional: an empty one falls back to the account's phone / email (see contact in the config call), and the call is refused with PHONE_OR_EMAIL_REQUIRED only when neither exists. Once the return holds a return code (on creation unless it awaits approval, else on approval) the customer is emailed the code, its QR code and a link to the return's status page, in the request's language, using the Client's own \"Return Confirmation\" email template or the built-in wording; data.confirmation_email in the response is the address it goes to, or null when none is sent.",
                "properties": {
                  "original_order_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "return_type": {
                    "type": "integer",
                    "enum": [
                      1,
                      2,
                      3,
                      4
                    ],
                    "description": "1 self-paid; 2 free return requiring approval; 3 own shipping label; 4 return barcode / QR code"
                  },
                  "return_channel_id": {
                    "oneOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "string",
                        "enum": [
                          "other"
                        ]
                      }
                    ],
                    "nullable": true
                  },
                  "return_address_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "return_reason_id": {
                    "type": "integer",
                    "nullable": true,
                    "description": "required unless the applicable requires_return_reason (the channel's, other_channel's or uploaded_label's from the config call) is false, in which case it is ignored"
                  },
                  "reference_number": {
                    "type": "string",
                    "nullable": true
                  },
                  "custom_channel_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "\"other\" channel: the carrier's name"
                  },
                  "return_name": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_address_1": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_address_2": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_city": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_province": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_country": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_postcode": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_telephone": {
                    "type": "string",
                    "nullable": true
                  },
                  "return_lat": {
                    "type": "number",
                    "nullable": true
                  },
                  "return_lng": {
                    "type": "number",
                    "nullable": true
                  },
                  "self_label_channel_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "type 3: the carrier of the uploaded label"
                  },
                  "self_label_file": {
                    "type": "string",
                    "format": "binary",
                    "nullable": true,
                    "description": "multipart upload for types 3 and 4"
                  },
                  "self_label_file_base64": {
                    "type": "string",
                    "nullable": true,
                    "description": "JSON alternative to self_label_file; bare base64 or a data URL"
                  },
                  "self_label_file_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "file name carrying the extension, with self_label_file_base64"
                  },
                  "form_data": {
                    "type": "object",
                    "additionalProperties": true,
                    "nullable": true
                  },
                  "pickup_name": {
                    "type": "string"
                  },
                  "pickup_address_1": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_address_2": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_city": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_province": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_country": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_postcode": {
                    "type": "string",
                    "nullable": true
                  },
                  "pickup_lat": {
                    "type": "number",
                    "nullable": true
                  },
                  "pickup_lng": {
                    "type": "number",
                    "nullable": true
                  },
                  "pickup_telephone": {
                    "type": "string",
                    "nullable": true
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "nullable": true
                  },
                  "return_description": {
                    "type": "string",
                    "nullable": true
                  },
                  "notes": {
                    "type": "string",
                    "nullable": true
                  },
                  "coupon_code": {
                    "type": "string",
                    "maxLength": 100,
                    "nullable": true,
                    "description": "Coupon for the channel's fee (a promotion of service type return_request). Ignored on a free channel."
                  },
                  "home_pickup": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Optional. true asks for the parcel to be picked up at the pickup address, through a channel whose home_pickup (config call) is not null. pickup_address_1, pickup_city, pickup_country and pickup_postcode are then required whatever the channel's pickup_address_mode, and the pickup fee is charged with the return fee. Omitted or false keeps the previous behaviour."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Return request created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Return request created.",
                  "data": {
                    "id": 901,
                    "status": 1,
                    "return_code": "RTN-TEST",
                    "return_methods": [
                      1,
                      2
                    ],
                    "return_type_code": "self_paid",
                    "return_type_name": "Self-paid return",
                    "custom_channel_name": null,
                    "self_label_file_url": null,
                    "return_code_value": null,
                    "return_code_symbology": null,
                    "form_data": null,
                    "return_order_id": 55012,
                    "home_pickup": true,
                    "fee": {
                      "amount": 20.0,
                      "pickup_fee": 8.0,
                      "discount": 5.0,
                      "charged": 23.0,
                      "currency": "CAD",
                      "promotion_name": "Spring returns",
                      "coupon_code": null,
                      "refunded": false,
                      "refunded_at": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.return"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Refused. Besides the field errors, a priced channel answers COUPON_INVALID (the coupon does not apply; errors.coupon_code) or INSUFFICIENT_BALANCE (errors.amount, errors.balance, errors.shortfall). With home_pickup: HOME_PICKUP_NOT_OFFERED (the channel does not offer home pickup; errors.home_pickup) or HOME_PICKUP_UNAVAILABLE (errors.home_pickup is the message, errors.reason is disabled, address_required, out_of_area or not_priced).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "code": {
                      "type": "string",
                      "example": "INSUFFICIENT_BALANCE"
                    },
                    "message": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": false,
                  "code": "INSUFFICIENT_BALANCE",
                  "message": "Your balance does not cover the return fee of 15.00. Top up at least 5.00.",
                  "errors": {
                    "amount": 15.0,
                    "balance": 10.0,
                    "shortfall": 5.0
                  }
                }
              }
            }
          }
        },
        "x-route-name": "openapp.returns.create",
        "x-graphql": "platformAppCreateReturn",
        "x-capability": "locker.return"
      }
    },
    "/app/v1/returns/{returnId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Show a customer return request",
        "description": "Returns an existing customer-owned ReturnRequest with pickup, destination, reason, channel and status details. The return carries fee: the channel fee charged when it was created ({amount, pickup_fee, discount, charged, currency, promotion_name, coupon_code, refunded, refunded_at}), or null on a free return. pickup_fee is the home pickup part of charged, null without a home pickup. home_pickup (boolean) tells whether the parcel is picked up at the pickup address; once the return is approved its pickup order is return_order_id. Additive: `wallet` — absolute Apple (.pkpass) and Google (save link) card links valid 2 h, or null when the Client has wallet cards off (docs/APP-UNIVERSAL-TRACKING-DESIGN.md UT7). Needs the locker.return capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppReturn",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "returnId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Return detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 901,
                    "status": 1,
                    "return_code": "RTN-TEST",
                    "destination": {
                      "name": "Return warehouse"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.return"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.returns.show",
        "x-graphql": "platformAppReturn",
        "x-capability": "locker.return"
      }
    },
    "/app/v1/returns/{returnId}/cancel": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Cancel a customer return request",
        "description": "Cancels an eligible pending or approved ReturnRequest that has not produced a return order, and appends the normal operation record. The return carries fee: the channel fee charged when it was created ({amount, discount, charged, currency, promotion_name, coupon_code, refunded, refunded_at}), or null on a free return. Needs the locker.return capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppCancelReturn",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "returnId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Return cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Return request cancelled.",
                  "data": {
                    "id": 901,
                    "status": 4,
                    "can_cancel": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.return"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "409": {
            "description": "The return can no longer be cancelled"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.returns.cancel",
        "x-graphql": "platformAppCancelReturn",
        "x-capability": "locker.return"
      }
    },
    "/app/v1/returns/config": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get App return configuration",
        "description": "Returns the authenticated customer’s existing return-center eligibility, channels, Client-owned addresses, reasons and effective SmartLocker return methods. Each channel carries logo_url: the absolute URL of the logo the Client uploaded for it, or null. guide holds the Client's own wording for the app's return guide pages (platform, upload, confirm, success), each with title and description in the requested locale; null means the app shows its built-in text. Each channel also carries its step 2 of the return guide: return_code_upload_mode (1 image required, 2 optional, 3 not asked), upload_step {tab, title, description} in the requested locale (null where the channel left it empty) and reference_number_description. Each channel carries fee: what a return through it costs this customer ({amount, discount, total, currency, promotion_name, coupon_code}), with the best automatic promotion already taken off, or null when the channel is free. The fee is taken from the customer's balance when the return is created. Each channel carries approval_mode: which returns through it wait for the Client's approval (1 only free returns, 2 all, 3 none). Each channel carries home_pickup: null when the channel does not offer home pickup, otherwise {fee_mode, fee, charges_return_fee, limited_to_regions}. fee_mode is fixed, price_plan or free; fee is the fixed amount, 0 when free, and null on price_plan (the price depends on the pickup address and comes from the fee quote). charges_return_fee false means the pickup fee replaces the return fee. limited_to_regions true means the pickup is offered only in some areas; the fee quote tells whether an address is served. Needs the locker.return capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppReturnConfiguration",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Preferred response locale",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Return configuration",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "return_types": [
                      {
                        "id": 1,
                        "code": "self_paid",
                        "name": "Self-paid return",
                        "requires_approval": false,
                        "requires_channel": true,
                        "requires_upload": false,
                        "requires_channel_name": false,
                        "requires_reference_number": false
                      },
                      {
                        "id": 2,
                        "code": "free_return",
                        "name": "Free return",
                        "requires_approval": true,
                        "requires_channel": true,
                        "requires_upload": false,
                        "requires_channel_name": false,
                        "requires_reference_number": false
                      },
                      {
                        "id": 3,
                        "code": "self_label",
                        "name": "Own shipping label",
                        "requires_approval": false,
                        "requires_channel": false,
                        "requires_upload": true,
                        "requires_channel_name": true,
                        "requires_reference_number": true
                      },
                      {
                        "id": 4,
                        "code": "return_barcode",
                        "name": "Return barcode / QR code",
                        "requires_approval": false,
                        "requires_channel": false,
                        "requires_upload": true,
                        "requires_channel_name": false,
                        "requires_reference_number": false
                      }
                    ],
                    "contact": {
                      "name": "Jane Doe",
                      "telephone": "+14165550123",
                      "email": "jane@example.com"
                    },
                    "requires_designated_address": true,
                    "other_channel": {
                      "available": true,
                      "id": "other",
                      "allowed_return_types": [
                        1
                      ],
                      "pickup_address_mode": 1,
                      "requires_return_reason": true
                    },
                    "uploaded_label": {
                      "pickup_address_mode": 1,
                      "accepted_extensions": [
                        "pdf",
                        "png",
                        "jpg",
                        "jpeg"
                      ],
                      "max_size_kb": 10240,
                      "requires_return_reason": true
                    },
                    "channels": [
                      {
                        "id": 4,
                        "name": "Online",
                        "description": null,
                        "logo_url": "https://admin.superroute.ca/storage/return-channels/online.png",
                        "reference_number_description": null,
                        "return_code_upload_mode": 1,
                        "upload_step": {
                          "tab": null,
                          "title": null,
                          "description": null
                        },
                        "reference_number_enabled": true,
                        "reference_number_required": false,
                        "return_methods": [
                          1,
                          2
                        ],
                        "allowed_return_types": [
                          1,
                          2
                        ],
                        "pickup_address_mode": 1,
                        "form": {
                          "id": 9,
                          "name": "Return details",
                          "fields": [
                            {
                              "code": "order_ref",
                              "name": "Order reference",
                              "type": "text",
                              "required": true,
                              "options": null,
                              "max_files": null
                            },
                            {
                              "code": "condition",
                              "name": "Item condition",
                              "type": "select",
                              "required": false,
                              "options": [
                                {
                                  "value": "new",
                                  "name": "Unopened"
                                },
                                {
                                  "value": "used",
                                  "name": "Opened"
                                }
                              ],
                              "max_files": null
                            }
                          ]
                        },
                        "addresses": [
                          {
                            "id": 6,
                            "name": "Return warehouse"
                          }
                        ],
                        "requires_return_reason": true,
                        "approval_mode": 1,
                        "home_pickup": {
                          "fee_mode": "fixed",
                          "fee": 8.0,
                          "charges_return_fee": true,
                          "limited_to_regions": false
                        },
                        "fee": {
                          "amount": 20.0,
                          "discount": 5.0,
                          "total": 15.0,
                          "currency": "CAD",
                          "promotion_name": "Spring returns",
                          "coupon_code": null
                        }
                      }
                    ],
                    "guide": {
                      "platform": {
                        "title": "Where did you buy it?",
                        "description": null
                      },
                      "upload": {
                        "title": null,
                        "description": null
                      },
                      "confirm": {
                        "title": null,
                        "description": null
                      },
                      "success": {
                        "title": null,
                        "description": null
                      }
                    },
                    "reasons": [
                      {
                        "id": 3,
                        "name": "Changed mind",
                        "requires_description": false
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.return"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.returns.config",
        "x-graphql": "platformAppReturnConfiguration",
        "x-capability": "locker.return"
      }
    },
    "/app/v1/returns/fee-quote": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Quote a return channel's fee",
        "operationId": "platformAppReturnFeeQuote",
        "description": "What a return through one channel costs the customer, with the coupon when given. fee is null when the channel is free. coupon_status: null without a coupon, applied, invalid (no such coupon for this customer, or its conditions are not met), or not_needed (free channel). balance is the customer's current balance. Nothing is charged here. Optional home_pickup (boolean) with pickup_postcode and pickup_country prices a home pickup at that address too: data.home_pickup is then {available, reason, message, fee, charges_return_fee, currency} (null when home_pickup was not sent). reason is null when available, else disabled (the channel does not offer it), address_required, out_of_area or not_priced; message is the reason in the request's language. fee is always the return fee alone (fee.total excludes the pickup fee); when an available pickup has charges_return_fee false, the pickup fee replaces the return fee and fee is null. The pickup fee is in home_pickup.fee. data.total is everything submitting would charge: the return fee after its promotion plus the pickup fee. Needs the locker.return capability on the token; answered exactly as the internal route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "return_channel_id"
                ],
                "properties": {
                  "return_channel_id": {
                    "type": "integer",
                    "example": 12
                  },
                  "coupon_code": {
                    "type": "string",
                    "maxLength": 100,
                    "nullable": true,
                    "example": "SPRING5"
                  },
                  "home_pickup": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Optional. true also prices a home pickup at pickup_postcode / pickup_country.",
                    "example": true
                  },
                  "pickup_postcode": {
                    "type": "string",
                    "maxLength": 16,
                    "nullable": true,
                    "example": "M5X 1A9"
                  },
                  "pickup_country": {
                    "type": "string",
                    "maxLength": 64,
                    "nullable": true,
                    "example": "CA"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fee quote",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "return_channel_id": {
                          "type": "integer"
                        },
                        "fee": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "amount": {
                              "type": "number"
                            },
                            "discount": {
                              "type": "number"
                            },
                            "total": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string"
                            },
                            "promotion_name": {
                              "type": "string",
                              "nullable": true
                            },
                            "coupon_code": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "coupon_status": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "applied",
                            "invalid",
                            "not_needed",
                            null
                          ]
                        },
                        "balance": {
                          "type": "number"
                        },
                        "home_pickup": {
                          "type": "object",
                          "nullable": true,
                          "description": "Null unless home_pickup was sent.",
                          "properties": {
                            "available": {
                              "type": "boolean"
                            },
                            "reason": {
                              "type": "string",
                              "nullable": true,
                              "enum": [
                                "disabled",
                                "address_required",
                                "out_of_area",
                                "not_priced",
                                null
                              ]
                            },
                            "message": {
                              "type": "string",
                              "nullable": true
                            },
                            "fee": {
                              "type": "number",
                              "nullable": true
                            },
                            "charges_return_fee": {
                              "type": "boolean",
                              "description": "false: the pickup fee replaces the return fee"
                            },
                            "currency": {
                              "type": "string"
                            }
                          }
                        },
                        "total": {
                          "type": "number",
                          "description": "Everything submitting would charge: the return fee after its promotion plus the pickup fee."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "return_channel_id": 12,
                    "fee": {
                      "amount": 20.0,
                      "discount": 5.0,
                      "total": 15.0,
                      "currency": "CAD",
                      "promotion_name": "Spring returns",
                      "coupon_code": "SPRING5"
                    },
                    "coupon_status": "applied",
                    "balance": 42.5,
                    "home_pickup": {
                      "available": true,
                      "reason": null,
                      "message": null,
                      "fee": 8.0,
                      "charges_return_fee": true,
                      "currency": "CAD"
                    },
                    "total": 23.0
                  }
                }
              }
            }
          },
          "422": {
            "description": "RETURN_CHANNEL_NOT_AVAILABLE: not one of the customer's channels"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.return"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.returns.fee-quote",
        "x-graphql": "platformAppReturnFeeQuote",
        "x-capability": "locker.return"
      }
    },
    "/app/v1/returns/{returnId}/confirmation-email": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Resend a return confirmation email",
        "description": "Sends the return code, its QR code and the status link to the email the return was created with, again, in the request's language, using the Client's \"Return Confirmation\" email template or the built-in wording. At most once a minute per return; can_resend_confirmation on the return says whether it can be sent at all. Needs the locker.return capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppResendReturnConfirmation",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "returnId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Confirmation email queued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "The confirmation email has been sent again to jane@example.com.",
                  "data": {
                    "confirmation_email": "jane@example.com"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.return"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "RETURN_EMAIL_NOT_AVAILABLE: no usable return code or email, or the Client switched the email off"
          },
          "429": {
            "description": "RETURN_EMAIL_RECENTLY_SENT: sent less than a minute ago"
          }
        },
        "x-route-name": "openapp.returns.confirmation-email",
        "x-graphql": "platformAppResendReturnConfirmation",
        "x-capability": "locker.return"
      }
    },
    "/app/v1/track": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Track any code (signed in)",
        "description": "Universal tracking (docs/APP-UNIVERSAL-TRACKING-DESIGN.md): one code of this Client in, whatever it is — `kind` parcel (tracking number), moving (moving code), storage (storage code), return (return code), shipping (shipping order code) or carrier_package (carrier tracking number). `tracking` is the OTEP public view (as /oteptrack); its `details` (addresses, dates, proof of delivery) and `summary.code` (pickup code) are present once `verified`. Send `answer` (last 4 digits of a phone on the shipment, or its postcode) to verify; `can_verify` says whether that is possible. A storage, return or shipping code is the drop-off code the sender holds, so `summary.code` is shown for those. `wallet` holds absolute Apple (.pkpass) and Google (save link) card links valid 2 h, or null when the Client has wallet cards off or the shipment offers no card. Errors: 404 TRACKING_NOT_FOUND (unknown code), 422 TRACKING_VERIFY_FAILED (wrong answer), 422 TRACKING_INVALID, 429 TRACKING_TOO_MANY. Signed in: the customer's own shipments are `owned` and verified without an answer, and the customer's own pickup codes resolve too (a pickup code of anyone else reads as not found); a partner locker pickup answers `kind` partner_delivery with `pickup_id` for GET .../pickups/{deliveryId}. Needs the tracking capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppTrack",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "identifier"
                ],
                "properties": {
                  "identifier": {
                    "type": "string",
                    "maxLength": 100,
                    "example": "R8K2Q7"
                  },
                  "answer": {
                    "type": "string",
                    "maxLength": 20,
                    "example": "4821"
                  },
                  "locale": {
                    "type": "string",
                    "example": "en"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What the code is and where it stands",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "kind": "return",
                    "identifier": "R8K2Q7",
                    "owned": false,
                    "verified": false,
                    "can_verify": true,
                    "summary": {
                      "stage": "send",
                      "status": "awaiting_dropoff",
                      "reference": "RMA-1042",
                      "place": null,
                      "deadline": null,
                      "code": "R8K2Q7"
                    },
                    "tracking": {
                      "otep_version": "0.1",
                      "profile": "parcel",
                      "subject": {
                        "identifier": "R8K2Q7",
                        "profile": "parcel"
                      },
                      "current_status": "booking_confirmed",
                      "current_phase": "pre_shipment",
                      "delivered": false,
                      "events": [
                        {
                          "occurred_at": "2026-10-18T09:12:00-04:00",
                          "status_code": "information_submitted",
                          "phase": "pre_shipment",
                          "location": null
                        },
                        {
                          "occurred_at": "2026-10-18T09:40:00-04:00",
                          "status_code": "booking_confirmed",
                          "phase": "pre_shipment",
                          "location": null
                        }
                      ]
                    },
                    "wallet": {
                      "apple": "https://track.example.com/wallet-card/en/return_request/1042/apple?code=1&expires=1760800000&signature=...",
                      "google": "https://track.example.com/wallet-card/en/return_request/1042/google?code=1&expires=1760800000&signature=..."
                    },
                    "pickup_id": null
                  }
                }
              }
            }
          },
          "404": {
            "description": "TRACKING_NOT_FOUND, or the App / Client is not available"
          },
          "422": {
            "description": "TRACKING_INVALID or TRACKING_VERIFY_FAILED"
          },
          "429": {
            "description": "TRACKING_TOO_MANY"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry tracking"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.track",
        "x-graphql": "platformAppTrack",
        "x-capability": "tracking"
      }
    },
    "/app/v1/quotes/{line}": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Quote a line without signing in",
        "description": "Public. The same service and per-Client settings as the /quotes page, so the app and the page quote alike; every quote is recorded. The body carries the line's fields as listed in the schema. A request with a bearer token of a customer of this Client is quoted on that account, anyone else as an anonymous visitor. Carrier lines (label, express) are limited to six per minute per caller and Client. Needs the quotes.public capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPublicQuote",
        "parameters": [
          {
            "name": "line",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "delivery",
                "pickup",
                "p2p",
                "express",
                "shipping",
                "label",
                "moving",
                "storage"
              ]
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "to_postcode": "M5V 2T6",
                "weight": 2.4,
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "result true with quote, or result false with not_covered_reason",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppQuoteAnswer"
                },
                "example": {
                  "result": true,
                  "quote": {
                    "line": "delivery",
                    "currency": "CAD",
                    "total": 12.4,
                    "token": "abcdefghijabcdefghijabcdefghijabcdefghij",
                    "valid_until": "2026-10-15T12:00:00-04:00",
                    "drive_minutes": 18,
                    "drive_from": "Toronto Depot"
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: the Client does not offer quotes in this app"
          },
          "422": {
            "description": "Invalid input, or a line the Client does not offer: result false with errors"
          },
          "429": {
            "description": "Carrier-line limit: result false, not_covered_reason too_many"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry quotes.public"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.quotes.quote",
        "x-graphql": "platformAppPublicQuote",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-capability": "quotes.public"
      }
    },
    "/app/v1/quotes/schema": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "The quote form a client offers without signing in",
        "description": "Public. The lines and their fields, the same schema the /quotes page renders from. A request with a bearer token of a customer of this Client sees only what that account may use. Needs the quotes.public capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPublicQuoteSchema",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The quote form",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppQuoteSchema"
                },
                "example": {
                  "result": true,
                  "schema": {
                    "business_name": "Northstar Courier",
                    "currency": "CAD",
                    "valid_days": 7,
                    "lines": {}
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: the Client does not offer quotes in this app"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry quotes.public"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.quotes.schema",
        "x-graphql": "platformAppPublicQuoteSchema",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-capability": "quotes.public"
      }
    },
    "/app/v1/locker-locations": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List app-enabled SmartLocker locations",
        "description": "Searches the selected Client’s complete active SmartLocker catalog with server-side text search, viewport bounds, service and availability filters, pagination and optional live locker-status/capacity summaries. Each item is an address location; locker_status_summary counts the actual locker devices below that location. The existing status field remains an aggregate for compatibility. Optional coordinates or an origin address sort results by distance; direct coordinates take precedence, while address fields use Superroute’s shared geocoding service. Each location carries guide: the summary of its indoor directions, or null. Answered exactly as the internal route.",
        "operationId": "platformAppLockerLocations",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "description": "Origin latitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "description": "Origin longitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "origin_address_1",
            "in": "query",
            "required": false,
            "description": "Selected customer address line 1 used when coordinates are not supplied",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          },
          {
            "name": "origin_address_2",
            "in": "query",
            "required": false,
            "description": "Selected customer address line 2",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          },
          {
            "name": "origin_city",
            "in": "query",
            "required": false,
            "description": "Selected customer address city",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "origin_province",
            "in": "query",
            "required": false,
            "description": "Selected customer address province or region",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "origin_country",
            "in": "query",
            "required": false,
            "description": "Selected customer address country name or ISO-2 code",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "origin_postcode",
            "in": "query",
            "required": false,
            "description": "Selected customer address postcode",
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Location name, city or postcode",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum locations",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Page size, up to 100",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "One-based result page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "north",
            "in": "query",
            "required": false,
            "description": "Viewport north latitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "south",
            "in": "query",
            "required": false,
            "description": "Viewport south latitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "east",
            "in": "query",
            "required": false,
            "description": "Viewport east longitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "west",
            "in": "query",
            "required": false,
            "description": "Viewport west longitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "pickup",
            "in": "query",
            "required": false,
            "description": "Narrows the list to locations that support pickup. Only applied when true; false, empty or omitted returns the unfiltered catalog.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "return",
            "in": "query",
            "required": false,
            "description": "Narrows the list to locations that accept returns. Only applied when true; false, empty or omitted returns the unfiltered catalog.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "online",
            "in": "query",
            "required": false,
            "description": "Narrows the list to locations whose aggregated status is online. Only applied when true; false, empty or omitted returns the unfiltered catalog.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "available",
            "in": "query",
            "required": false,
            "description": "Narrows the list to locations with at least one available compartment. Only applied when true; false, empty or omitted returns the unfiltered catalog.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "favorite",
            "in": "query",
            "required": false,
            "description": "Narrows the list to the signed-in customer’s favorites. Only applied when true; false, empty or omitted returns the unfiltered catalog.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "include_status",
            "in": "query",
            "required": false,
            "description": "Include batched runtime status and capacity summaries",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort by distance, name, favorite, recent or popular",
            "schema": {
              "type": "string",
              "enum": [
                "distance",
                "name",
                "favorite",
                "recent",
                "popular"
              ],
              "default": "distance"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Locker locations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": 81,
                        "name": "Downtown locker",
                        "address": "100 King Street",
                        "city": "Toronto",
                        "latitude": 43.6487,
                        "longitude": -79.3817,
                        "distance_km": 1.3,
                        "locker_count": 2,
                        "services": {
                          "pickup": true,
                          "return": true
                        },
                        "status": "online",
                        "locker_status_summary": {
                          "total": 2,
                          "online": 1,
                          "offline": 1,
                          "maintenance": 0,
                          "unknown": 0
                        },
                        "capacity": {
                          "estimated": true,
                          "source": "superroute_records",
                          "total": 24,
                          "available": 16,
                          "occupied": 6,
                          "reserved": 2,
                          "unavailable": 0,
                          "unknown": 0,
                          "occupancy_percent": 33.3
                        },
                        "is_favorite": true,
                        "view_count": 4,
                        "last_viewed_at": "2026-07-25T00:30:00-04:00"
                      }
                    ],
                    "origin": {
                      "latitude": 43.65,
                      "longitude": -79.38,
                      "source": "geocoded_address"
                    },
                    "pagination": {
                      "current_page": 1,
                      "per_page": 20,
                      "total": 1,
                      "last_page": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "The App, Client, role or required capability is not available"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.locker-locations.index",
        "x-graphql": "platformAppLockerLocations"
      }
    },
    "/app/v1/locker-locations/{locationId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Show a SmartLocker location",
        "description": "Returns location details plus the distance from optional coordinates or an origin address, a status count for the actual locker devices below the address, live status, door summary, compartment dimensions, estimated occupancy and services. Capacity is grouped by physical compartment size and estimated from Superroute inventory, active grid allocations and provider parcel-presence data when available. The location also carries guide: a summary of the indoor directions to its lockers (available, step_count, has_video, has_floor_plan, updated_at), or null when it has none; GET .../locker-locations/{locationId}/guide returns them. Answered exactly as the internal route.",
        "operationId": "platformAppLockerLocation",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "description": "Origin latitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "description": "Origin longitude",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "origin_address_1",
            "in": "query",
            "required": false,
            "description": "Selected customer address line 1 used when coordinates are not supplied",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          },
          {
            "name": "origin_address_2",
            "in": "query",
            "required": false,
            "description": "Selected customer address line 2",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          },
          {
            "name": "origin_city",
            "in": "query",
            "required": false,
            "description": "Selected customer address city",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "origin_province",
            "in": "query",
            "required": false,
            "description": "Selected customer address province or region",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "origin_country",
            "in": "query",
            "required": false,
            "description": "Selected customer address country name or ISO-2 code",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "origin_postcode",
            "in": "query",
            "required": false,
            "description": "Selected customer address postcode",
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Locker location detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 81,
                    "name": "Downtown locker",
                    "distance_km": 0.55,
                    "status": "online",
                    "locker_status_summary": {
                      "total": 1,
                      "online": 1,
                      "offline": 0,
                      "maintenance": 0,
                      "unknown": 0
                    },
                    "lockers": [
                      {
                        "id": 12,
                        "name": "Main entrance locker",
                        "code": "LK-12",
                        "provider": "superbox",
                        "status": "online",
                        "compartment_count": 24,
                        "compartments": {
                          "open": 0,
                          "closed": 23,
                          "fault": 1,
                          "unknown": 0
                        },
                        "capacity": {
                          "estimated": true,
                          "source": "superroute_records",
                          "total": 24,
                          "available": 16,
                          "occupied": 6,
                          "reserved": 1,
                          "unavailable": 1,
                          "unknown": 0,
                          "occupancy_percent": 29.2,
                          "sizes": [
                            {
                              "length_mm": 400,
                              "width_mm": 500,
                              "height_mm": 300,
                              "total": 12,
                              "available": 7,
                              "occupied": 4,
                              "reserved": 1,
                              "unavailable": 0,
                              "unknown": 0,
                              "occupancy_percent": 41.7
                            }
                          ]
                        },
                        "features": [
                          "pickup_package",
                          "dropoff"
                        ]
                      }
                    ],
                    "guide": {
                      "available": true,
                      "step_count": 3,
                      "has_video": true,
                      "has_floor_plan": true,
                      "updated_at": "2026-09-28T10:15:00-04:00"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "The App, Client, role or required capability is not available"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.locker-locations.show",
        "x-graphql": "platformAppLockerLocation"
      }
    },
    "/app/v1/locker-locations/{locationId}/guide": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Indoor directions to the lockers of a location",
        "description": "The indoor directions a location's operator wrote for finding its smart lockers: floor, entrance and summary, ordered steps each with an optional photo or video (with a cover image, size and duration for videos), and a floor plan with the position of each locker as a percentage of the image's width and height. Texts come in the Accept-Language language, else English, else the first language written. Only lockers this app lists at the location are marked. 404 LOCATION_GUIDE_NOT_FOUND when the location has no directions shown to customers; 404 LOCKER_LOCATION_NOT_FOUND when the location is not one this app lists. Each step's media_type is image, video (an uploaded file) or youtube (a YouTube video: media_url is its watch link, poster_url its thumbnail and youtube_id its id; open it in YouTube or embed it); youtube_id is null for other steps. Answered exactly as the internal route.",
        "operationId": "platformAppLockerLocationGuide",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Indoor directions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "location_id": 81,
                    "floor": "B1",
                    "entrance": "North entrance, next to the parking lot",
                    "summary": "The lockers are next to the food court, on the left of the escalator.",
                    "steps": [
                      {
                        "id": 11,
                        "position": 1,
                        "text": "Enter through the north entrance.",
                        "media_type": "image",
                        "media_url": "https://admin.superroute.ca/storage/location-guides/3/81/step1.jpg",
                        "poster_url": null,
                        "media_width": 1600,
                        "media_height": 1200,
                        "duration_seconds": null,
                        "file_size": 412345,
                        "youtube_id": null
                      },
                      {
                        "id": 12,
                        "position": 2,
                        "text": "Take the escalator down to B1 and turn left.",
                        "media_type": "video",
                        "media_url": "https://admin.superroute.ca/storage/location-guides/3/81/step2.mp4",
                        "poster_url": "https://admin.superroute.ca/storage/location-guides/3/81/step2.jpg",
                        "media_width": 1080,
                        "media_height": 1920,
                        "duration_seconds": 18,
                        "file_size": 9876543,
                        "youtube_id": null
                      },
                      {
                        "id": 13,
                        "position": 3,
                        "text": "The lockers are on your left.",
                        "media_type": "youtube",
                        "media_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
                        "poster_url": "https://img.youtube.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
                        "youtube_id": "dQw4w9WgXcQ",
                        "media_width": 16,
                        "media_height": 9,
                        "duration_seconds": null,
                        "file_size": null
                      }
                    ],
                    "floor_plan": {
                      "url": "https://admin.superroute.ca/storage/location-guides/3/81/plan.png",
                      "width": 2000,
                      "height": 1400,
                      "markers": [
                        {
                          "locker_id": 12,
                          "locker_name": "Main entrance locker",
                          "x_percent": 62.5,
                          "y_percent": 41.2
                        }
                      ]
                    },
                    "updated_at": "2026-09-28T10:15:00-04:00"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Location not found, or it has no indoor directions"
          }
        },
        "x-route-name": "openapp.locker-locations.guide",
        "x-graphql": "platformAppLockerLocationGuide"
      }
    },
    "/app/v1/locker-locations/{locationId}/guide/feedback": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Answer whether the lockers were found",
        "description": "Answer whether the lockers of a location were found with its indoor directions (found: true or false). One answer per user, location and day; a second answer the same day replaces the first. The counts are shown to the location's operator. 404 LOCATION_GUIDE_NOT_FOUND when the location has no directions shown to customers. Answered exactly as the internal route.",
        "operationId": "platformAppLockerLocationGuideFeedback",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "found"
                ],
                "properties": {
                  "found": {
                    "type": "boolean",
                    "description": "true when the lockers were found"
                  }
                }
              },
              "example": {
                "found": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Answer recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "location_id": 81,
                    "found": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Location not found, or it has no indoor directions"
          },
          "422": {
            "description": "Validation error"
          }
        },
        "x-route-name": "openapp.locker-locations.guide-feedback",
        "x-graphql": "platformAppLockerLocationGuideFeedback"
      }
    },
    "/app/v1/locker-locations/{locationId}/preference": {
      "put": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Update a customer SmartLocker preference",
        "description": "Idempotently favorites or unfavorites a SmartLocker and records customer visits for recent and frequently used location ranking. Preference data is scoped by App assignment, Client and customer. Answered exactly as the internal route.",
        "operationId": "platformAppUpdateLockerPreference",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 81
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "favorite": {
                    "type": "boolean"
                  },
                  "viewed": {
                    "type": "boolean"
                  }
                },
                "anyOf": [
                  {
                    "required": [
                      "favorite"
                    ]
                  },
                  {
                    "required": [
                      "viewed"
                    ]
                  }
                ]
              },
              "example": {
                "favorite": true,
                "viewed": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated locker preference",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "data": {
                    "location_id": 81,
                    "is_favorite": true,
                    "view_count": 4,
                    "last_viewed_at": "2026-07-25T00:30:00-04:00"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "The App, Client, role or required capability is not available"
          },
          "404": {
            "description": "SmartLocker location not found"
          },
          "422": {
            "description": "Invalid request"
          },
          "503": {
            "description": "Preference storage migration is not available yet"
          }
        },
        "x-route-name": "openapp.locker-locations.preference",
        "x-graphql": "platformAppUpdateLockerPreference"
      }
    },
    "/app/v1/pickups": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List customer locker pickups",
        "description": "Lists only PartnerLocker deliveries owned by the authenticated customer. Ownership is matched against the normalized, encrypted-recipient hash and selected Client. Additive: `can_hand_over` and `handoff` (null, or {name, channel, contact (masked), handed_over_at}); while handed over `pickup_code` and `pickup_qr_value` are null and `remote_open_available` is false. The pickup's location carries guide: the summary of the indoor directions to its lockers (available, step_count, has_video, has_floor_plan, updated_at), or null; GET .../locker-locations/{locationId}/guide returns them. Needs the locker.pickup capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPickups",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Pickup status",
            "schema": {
              "type": "string",
              "enum": [
                "not_ready",
                "ready",
                "partial",
                "completed"
              ]
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Customer pickups",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": 72,
                        "delivery_no": "PLD-01",
                        "pickup_status": "ready",
                        "pickup_code": "482913",
                        "pickup_qr_value": "482913",
                        "remote_open_available": true
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.pickup"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.pickups.index",
        "x-graphql": "platformAppPickups",
        "x-capability": "locker.pickup"
      }
    },
    "/app/v1/pickups/{deliveryId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Show a customer locker pickup",
        "description": "Returns pickup code, QR payload, location, compartment and package state for a customer-owned delivery. Additive: `can_hand_over` and `handoff` (null, or {name, channel, contact (masked), handed_over_at}); while handed over `pickup_code` and `pickup_qr_value` are null and `remote_open_available` is false. The pickup's location carries guide: the summary of the indoor directions to its lockers (available, step_count, has_video, has_floor_plan, updated_at), or null; GET .../locker-locations/{locationId}/guide returns them. Additive: `wallet` — absolute Apple (.pkpass) and Google (save link) card links valid 2 h, or null when the Client has wallet cards off (docs/APP-UNIVERSAL-TRACKING-DESIGN.md UT7). Needs the locker.pickup capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPickup",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pickup detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 72,
                    "pickup_status": "ready",
                    "pickup_code": "482913",
                    "location": {
                      "id": 81,
                      "name": "Downtown locker"
                    },
                    "items": [
                      {
                        "id": 1,
                        "compartment_number": "A03",
                        "status": "ready"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.pickup"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.pickups.show",
        "x-graphql": "platformAppPickup",
        "x-capability": "locker.pickup"
      }
    },
    "/app/v1/pickups/{deliveryId}/collect": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Collect and remotely open a locker pickup",
        "description": "Requires the effective locker.remote_open capability and explicit customer confirmation. Reuses WarehouseSelfPickup, SmartLocker door verification, compartment locks, inventory settlement and audit services. Needs the locker.remote_open capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppCollectPickup",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_confirmed"
                ],
                "properties": {
                  "user_confirmed": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  }
                }
              },
              "example": {
                "user_confirmed": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Locker opened and pickup settled, possibly with a partial result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "picked_up_count": 1,
                    "partial_success": false,
                    "opened": [
                      {
                        "compartment_number": "A03"
                      }
                    ],
                    "failed": []
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.remote_open"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "409": {
            "description": "Pickup is already in progress or has no usable pickup code; LOCKER_PICKUP_HANDED_OVER while the pickup is handed to somebody else"
          },
          "422": {
            "description": "Invalid request"
          },
          "502": {
            "description": "The SmartLocker operation could not be confirmed"
          }
        },
        "x-route-name": "openapp.pickups.collect",
        "x-graphql": "platformAppCollectPickup",
        "x-capability": "locker.remote_open"
      }
    },
    "/app/v1/pickups/{deliveryId}/handoff": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Hand a locker pickup to somebody else",
        "description": "Requires locker.pickup. Only a ready or partially collected pickup. The pickup code is rotated: the owner's code stops opening the door at once and the new code is sent only to the named person by SMS (phone) or email, in `language` (default: the request's Accept-Language). Give exactly one of `phone` or `email`; a phone number is read in the pickup location's country. While handed over the owner's pickup carries no code, `remote_open_available` is false, collect is refused (409 LOCKER_PICKUP_HANDED_OVER) and `handoff` names the person with a masked contact. Handing over again replaces the earlier handover and its code. Only the masked contact is stored. Needs the locker.pickup capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppHandOverPickup",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 40,
                    "description": "Required without email"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Required without phone"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "chs",
                      "cht",
                      "de",
                      "es",
                      "fr",
                      "it",
                      "nl",
                      "pt",
                      "sr",
                      "hu",
                      "pl",
                      "sk",
                      "cs"
                    ]
                  }
                }
              },
              "example": {
                "name": "Ann",
                "phone": "+14165550100",
                "language": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Handed over; the pickup as the owner now sees it",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 72,
                    "pickup_status": "ready",
                    "pickup_code": null,
                    "pickup_qr_value": null,
                    "remote_open_available": false,
                    "can_hand_over": true,
                    "handoff": {
                      "name": "Ann",
                      "channel": "sms",
                      "contact": "***0100",
                      "handed_over_at": "2026-09-27T10:15:00-04:00"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.pickup"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "409": {
            "description": "LOCKER_HANDOFF_UNAVAILABLE: the pickup is not ready or no longer collectable"
          },
          "422": {
            "description": "LOCKER_HANDOFF_CONTACT_INVALID (phone or email not usable, or both given) or LOCKER_HANDOFF_SELF (the owner's own contact)"
          },
          "502": {
            "description": "LOCKER_HANDOFF_SEND_FAILED: the code could not be sent; nothing changed and the owner keeps the current code"
          }
        },
        "x-route-name": "openapp.pickups.handoff",
        "x-graphql": "platformAppHandOverPickup",
        "x-capability": "locker.pickup"
      }
    },
    "/app/v1/pickups/{deliveryId}/handoff/revoke": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Take back a handed-over locker pickup",
        "description": "Requires locker.pickup. The pickup code is rotated again: the other person's code stops working and the owner's pickup shows the new code. Needs the locker.pickup capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppTakeBackPickup",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Taken back; the pickup with its new code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 72,
                    "pickup_code": "K7Q2MX",
                    "pickup_qr_value": "K7Q2MX",
                    "remote_open_available": true,
                    "can_hand_over": true,
                    "handoff": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.pickup"
          },
          "404": {
            "description": "The requested customer-owned resource was not found"
          },
          "409": {
            "description": "LOCKER_HANDOFF_NOT_ACTIVE (nothing handed over) or LOCKER_HANDOFF_UNAVAILABLE (no longer collectable)"
          }
        },
        "x-route-name": "openapp.pickups.handoff.revoke",
        "x-graphql": "platformAppTakeBackPickup",
        "x-capability": "locker.pickup"
      }
    },
    "/app/v1/locker-storage/rentals": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List the renter's stored luggage",
        "description": "Bags the signed-in customer stored in the business's smart lockers, newest first. A rental is the customer's when it is bound to the account, or bound to nobody and stored under the account's e-mail or a verified phone number. scope=current lists bags still held (in a compartment or away with the operator), scope=past the rest. Each item carries its bill (amount so far, and how to pay it), its relay (where a bag away from its cabinet is) and any weight difference owed. No pickup code and no contact are returned; the compartment number only while the bag is in it. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageRentals",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "current | past"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "1–50, default 20"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": 8801,
                        "status": "relayed",
                        "status_label": "Relayed",
                        "site": {
                          "id": 700,
                          "name": "Central Station",
                          "address": "1 Main St",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H3B 1A1",
                          "country": "CA",
                          "latitude": 45.5,
                          "longitude": -73.57
                        },
                        "cabinet": {
                          "id": 312,
                          "code": "CAB-A"
                        },
                        "compartment_number": null,
                        "compartment_type": "Medium",
                        "bound_to_account": true,
                        "started_at": "2026-09-24T09:10:00-04:00",
                        "expires_at": "2026-09-26T09:10:00-04:00",
                        "ended_at": null,
                        "declared_return_at": "2026-09-27T12:00:00-04:00",
                        "bill": {
                          "charged": true,
                          "paid": false,
                          "amount": 24.0,
                          "currency": "CAD",
                          "paid_at": null,
                          "due_now": true,
                          "payment": {
                            "subject_type": "locker",
                            "subject_id": 8801,
                            "amount": 24.0,
                            "currency": "CAD",
                            "payable_in_app": true,
                            "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                          }
                        },
                        "relay": {
                          "id": 55,
                          "rental_id": 8801,
                          "rental_status": "relayed",
                          "status": "at_hub",
                          "from_site": {
                            "id": 700,
                            "name": "Central Station"
                          },
                          "return": {
                            "kind": "shipment",
                            "site": null,
                            "address": {
                              "name": "A. Renter",
                              "address_1": "10 Rue Sainte-Catherine",
                              "city": "Montreal",
                              "province": "QC",
                              "postcode": "H2X 1K4",
                              "country": "CA"
                            },
                            "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                            "paid": false,
                            "shipment": {
                              "carrier": null,
                              "tracking_number": null
                            }
                          },
                          "onward": {
                            "kind": "shipment",
                            "status": "weight_hold",
                            "mode": "table",
                            "channel": "label",
                            "weight_tier_kg": 10,
                            "weighed_kg": 12.4,
                            "declared": {
                              "weight_kg": 9.5
                            },
                            "measured": {
                              "weight_kg": 12.4
                            },
                            "option": {
                              "key": "t12",
                              "mode": "table",
                              "channel": "label",
                              "carrier": "Canada Post",
                              "service": "Expedited",
                              "service_code": "DOM.EP",
                              "transit_days": 2,
                              "price": 32.0,
                              "currency": "CAD"
                            },
                            "price": 32.0,
                            "currency": "CAD",
                            "valid_until": "2026-10-01T09:10:00-04:00",
                            "hold": {
                              "from_tier_kg": 10,
                              "tier_kg": 20,
                              "extra": 8.0,
                              "paid": false
                            }
                          },
                          "return_by": "2026-09-27T10:00:00-04:00",
                          "declared_return_at": "2026-09-27T12:00:00-04:00",
                          "warn_until": null,
                          "taken_out_at": "2026-09-24T15:02:00-04:00",
                          "hub_received_at": "2026-09-24T17:40:00-04:00",
                          "hub_shipped_at": null,
                          "returned_at": null,
                          "cancelled_at": null,
                          "cancel_reason": null,
                          "hub_days": null,
                          "price": {
                            "hub_per_day": 3.0,
                            "relay_fee": 5.0,
                            "address_return_fee": null,
                            "alt_site_fee": null,
                            "shipment_fee": 32.0,
                            "free_hub_hours": 24,
                            "currency": "CAD"
                          },
                          "created_at": "2026-09-24T14:00:00-04:00"
                        },
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "subject_type": "luggage_hold",
                          "subject_id": 55,
                          "amount": 8.0,
                          "currency": "CAD",
                          "payable_in_app": true,
                          "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                        }
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 20,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.index",
        "x-graphql": "platformAppLockerStorageRentals",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Show one stored bag",
        "description": "One of the renter's stored bags, with the choices open now under options: keep it during the warning window, collect at another cabinet (pickup_site), change the return cabinet or time while it is away, have it delivered, ship it, resend the code. Times are ISO 8601; timezone is the business's, in which times the renter types are read. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageRental",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No stored bag with that id belongs to this customer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_NOT_FOUND",
                  "message": "This stored item was not found."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.show",
        "x-graphql": "platformAppLockerStorageRental",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/claim": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Add a stored bag by its code",
        "description": "For a bag stored under a contact the account does not hold: the pickup code plus the last four digits of the phone it was stored under, or that whole e-mail. Binds the rental to the account; from then on a pickup at the cabinet is paid from the balance when it covers the bill. Every miss answers the same 404. Throttled to 5 requests a minute. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageClaim",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "code",
                  "contact"
                ],
                "properties": {
                  "code": {
                    "type": "string",
                    "maxLength": 32
                  },
                  "contact": {
                    "type": "string",
                    "maxLength": 191
                  }
                }
              },
              "example": {
                "code": "K7Q2M9",
                "contact": "0100"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The code and contact do not match a live stored bag of this business that is free to add",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_CODE_NOT_RECOGNISED",
                  "message": "The code and contact do not match a stored item."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.claim",
        "x-graphql": "platformAppLockerStorageClaim",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/delivery": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Have the bag delivered to an address",
        "description": "Delivery by the operator's own drivers, by deliver_at (business local time). The bag leaves its compartment if it is still there; the bill, including the delivery fee, is due before the delivery is planned — see data.bill.payment (pay in the app with pay/requests when payable_in_app, or at pay_url). Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageDelivery",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address",
                  "deliver_at"
                ],
                "properties": {
                  "address": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "telephone": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "address_1": {
                        "type": "string"
                      },
                      "address_2": {
                        "type": "string"
                      },
                      "city": {
                        "type": "string"
                      },
                      "province": {
                        "type": "string"
                      },
                      "postcode": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string"
                      },
                      "note": {
                        "type": "string"
                      }
                    }
                  },
                  "deliver_at": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "address": {
                  "name": "A. Renter",
                  "telephone": "+15145550100",
                  "address_1": "10 Rue Sainte-Catherine",
                  "city": "Montreal",
                  "province": "QC",
                  "postcode": "H2X 1K4",
                  "country": "CA"
                },
                "deliver_at": "2026-09-27 18:00"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Delivery to the address is requested. Pay the bill on this page to confirm it.",
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "422": {
            "description": "Address or time missing"
          },
          "409": {
            "description": "LOCKER_STORAGE_ADDRESS_NOT_COVERED, LOCKER_STORAGE_ADDRESS_UNPRICED, or not offered now",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_ACTION_UNAVAILABLE",
                  "message": "This action is not available right now."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.delivery",
        "x-graphql": "platformAppLockerStorageDelivery",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/keep": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Keep the bag in its compartment",
        "description": "Answers the warning sent before an operator rule moves a long-stored bag to the hub (options.keep is true until options.warn_until). Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageKeep",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Your luggage stays in its compartment.",
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "409": {
            "description": "No warning is open for this bag",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_ACTION_UNAVAILABLE",
                  "message": "This action is not available right now."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.keep",
        "x-graphql": "platformAppLockerStorageKeep",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/onward-quote": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Price delivery and shipment to an address",
        "description": "Reads only. own_delivery answers delivery by the operator's drivers (only inside its delivery area); shipment lists carrier label and courier options by price, for the weight band given or derived from weight_kg. A choice is made with /delivery or /shipment. Throttled to 20 requests a minute. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageOnwardQuote",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address"
                ],
                "properties": {
                  "address": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "telephone": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "address_1": {
                        "type": "string"
                      },
                      "address_2": {
                        "type": "string"
                      },
                      "city": {
                        "type": "string"
                      },
                      "province": {
                        "type": "string"
                      },
                      "postcode": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string"
                      },
                      "note": {
                        "type": "string"
                      }
                    }
                  },
                  "weight_tier_kg": {
                    "type": "integer"
                  },
                  "weight_kg": {
                    "type": "number"
                  },
                  "dimensions_cm": {
                    "type": "object",
                    "properties": {
                      "length": {
                        "type": "number"
                      },
                      "width": {
                        "type": "number"
                      },
                      "height": {
                        "type": "number"
                      }
                    }
                  }
                }
              },
              "example": {
                "address": {
                  "name": "A. Renter",
                  "telephone": "+15145550100",
                  "address_1": "10 Rue Sainte-Catherine",
                  "city": "Montreal",
                  "province": "QC",
                  "postcode": "H2X 1K4",
                  "country": "CA"
                },
                "weight_kg": 9.5
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "own_delivery": {
                      "available": true,
                      "reason": null,
                      "fee": 18.0,
                      "currency": "CAD",
                      "mode": "flat"
                    },
                    "shipment": {
                      "available": true,
                      "reason": null,
                      "mode": "table",
                      "currency": "CAD",
                      "weight_tier_kg": 10,
                      "weight_tiers_kg": [
                        5,
                        10,
                        20,
                        32
                      ],
                      "measure": {
                        "weight_kg": 9.5,
                        "length_cm": null,
                        "width_cm": null,
                        "height_cm": null
                      },
                      "options": [
                        {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        {
                          "key": "s4",
                          "mode": "courier",
                          "channel": "courier",
                          "carrier": "City Courier",
                          "service": "Same day",
                          "service_code": null,
                          "transit_days": 0,
                          "price": 41.5,
                          "currency": "CAD"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Address missing name, address_1 or city"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.onward-quote",
        "x-graphql": "platformAppLockerStorageOnwardQuote",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/pickup-site": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Collect at another cabinet",
        "description": "While the bag is in its compartment: collect it at one of options.pickup_site.choices instead (the operator carries it through its hub; options.pickup_site.fee is added to the bill, paid at pickup). While it is away and its return is not yet planned: bring it back to one of options.return_site.choices. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStoragePickupSite",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "warehouse_id"
                ],
                "properties": {
                  "warehouse_id": {
                    "type": "integer"
                  }
                }
              },
              "example": {
                "warehouse_id": 701
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Your luggage will be moved to the chosen cabinet. Your code stays the same.",
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "409": {
            "description": "Not a choice for this bag now",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_ACTION_UNAVAILABLE",
                  "message": "This action is not available right now."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.pickup-site",
        "x-graphql": "platformAppLockerStoragePickupSite",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/pickup-site/cancel": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Collect where the bag is after all",
        "description": "Undo a pickup-site choice before the bag has left its compartment. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStoragePickupSiteCancel",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "The move is cancelled. Collect your luggage where you left it.",
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The bag has already left, or no such choice was made",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_ACTION_UNAVAILABLE",
                  "message": "This action is not available right now."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.pickup-site-cancel",
        "x-graphql": "platformAppLockerStoragePickupSiteCancel",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/resend-code": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Send the pickup code again",
        "description": "To the contact the bag was stored under, never to the account asking. Throttled to 3 requests in 10 minutes. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageResendCode",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Your code has been sent again.",
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The bag is no longer held, or has no contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_ACTION_UNAVAILABLE",
                  "message": "This action is not available right now."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.resend-code",
        "x-graphql": "platformAppLockerStorageResendCode",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/return-time": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Change when you come back",
        "description": "For a bag that is away: when the renter will come back for it, in the business's local time (Y-m-d H:i), no later than options.return_time.latest. The return trip is re-planned to arrive before it. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageReturnTime",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "return_at"
                ],
                "properties": {
                  "return_at": {
                    "type": "string",
                    "example": "2026-09-28 14:00"
                  }
                }
              },
              "example": {
                "return_at": "2026-09-28 14:00"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Your return time has been changed.",
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "422": {
            "description": "Not a time"
          },
          "409": {
            "description": "Outside the allowed window, or the return is already on its way",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_ACTION_UNAVAILABLE",
                  "message": "This action is not available right now."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.return-time",
        "x-graphql": "platformAppLockerStorageReturnTime",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/locker-storage/rentals/{id}/shipment": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Ship the bag with a carrier or courier",
        "description": "One option key from onward-quote, with the same address and weight. The option is re-quoted and must still be offered. Paid before the bag ships; if the hub weighs it heavier than declared, the difference appears as data.hold and must be paid before it leaves. Needs name, telephone, address_1, city, postcode and country. Requires the locker.storage capability (403 APP_CAPABILITY_DISABLED otherwise). Needs the locker.storage capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerStorageShipment",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Rental id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address",
                  "option"
                ],
                "properties": {
                  "address": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "telephone": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "address_1": {
                        "type": "string"
                      },
                      "address_2": {
                        "type": "string"
                      },
                      "city": {
                        "type": "string"
                      },
                      "province": {
                        "type": "string"
                      },
                      "postcode": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string"
                      },
                      "note": {
                        "type": "string"
                      }
                    }
                  },
                  "option": {
                    "type": "string"
                  },
                  "weight_tier_kg": {
                    "type": "integer"
                  },
                  "weight_kg": {
                    "type": "number"
                  },
                  "dimensions_cm": {
                    "type": "object",
                    "properties": {
                      "length": {
                        "type": "number"
                      },
                      "width": {
                        "type": "number"
                      },
                      "height": {
                        "type": "number"
                      }
                    }
                  }
                }
              },
              "example": {
                "address": {
                  "name": "A. Renter",
                  "telephone": "+15145550100",
                  "address_1": "10 Rue Sainte-Catherine",
                  "city": "Montreal",
                  "province": "QC",
                  "postcode": "H2X 1K4",
                  "country": "CA"
                },
                "option": "t12",
                "weight_kg": 9.5
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Your shipment is set. Pay the bill on this page to confirm it.",
                  "data": {
                    "id": 8801,
                    "status": "relayed",
                    "status_label": "Relayed",
                    "site": {
                      "id": 700,
                      "name": "Central Station",
                      "address": "1 Main St",
                      "city": "Montreal",
                      "province": "QC",
                      "postcode": "H3B 1A1",
                      "country": "CA",
                      "latitude": 45.5,
                      "longitude": -73.57
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "compartment_number": null,
                    "compartment_type": "Medium",
                    "bound_to_account": true,
                    "started_at": "2026-09-24T09:10:00-04:00",
                    "expires_at": "2026-09-26T09:10:00-04:00",
                    "ended_at": null,
                    "declared_return_at": "2026-09-27T12:00:00-04:00",
                    "bill": {
                      "charged": true,
                      "paid": false,
                      "amount": 24.0,
                      "currency": "CAD",
                      "paid_at": null,
                      "due_now": true,
                      "payment": {
                        "subject_type": "locker",
                        "subject_id": 8801,
                        "amount": 24.0,
                        "currency": "CAD",
                        "payable_in_app": true,
                        "pay_url": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=…"
                      }
                    },
                    "relay": {
                      "id": 55,
                      "rental_id": 8801,
                      "rental_status": "relayed",
                      "status": "at_hub",
                      "from_site": {
                        "id": 700,
                        "name": "Central Station"
                      },
                      "return": {
                        "kind": "shipment",
                        "site": null,
                        "address": {
                          "name": "A. Renter",
                          "address_1": "10 Rue Sainte-Catherine",
                          "city": "Montreal",
                          "province": "QC",
                          "postcode": "H2X 1K4",
                          "country": "CA"
                        },
                        "address_line": "10 Rue Sainte-Catherine, Montreal QC H2X 1K4",
                        "paid": false,
                        "shipment": {
                          "carrier": null,
                          "tracking_number": null
                        }
                      },
                      "onward": {
                        "kind": "shipment",
                        "status": "weight_hold",
                        "mode": "table",
                        "channel": "label",
                        "weight_tier_kg": 10,
                        "weighed_kg": 12.4,
                        "declared": {
                          "weight_kg": 9.5
                        },
                        "measured": {
                          "weight_kg": 12.4
                        },
                        "option": {
                          "key": "t12",
                          "mode": "table",
                          "channel": "label",
                          "carrier": "Canada Post",
                          "service": "Expedited",
                          "service_code": "DOM.EP",
                          "transit_days": 2,
                          "price": 32.0,
                          "currency": "CAD"
                        },
                        "price": 32.0,
                        "currency": "CAD",
                        "valid_until": "2026-10-01T09:10:00-04:00",
                        "hold": {
                          "from_tier_kg": 10,
                          "tier_kg": 20,
                          "extra": 8.0,
                          "paid": false
                        }
                      },
                      "return_by": "2026-09-27T10:00:00-04:00",
                      "declared_return_at": "2026-09-27T12:00:00-04:00",
                      "warn_until": null,
                      "taken_out_at": "2026-09-24T15:02:00-04:00",
                      "hub_received_at": "2026-09-24T17:40:00-04:00",
                      "hub_shipped_at": null,
                      "returned_at": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "hub_days": null,
                      "price": {
                        "hub_per_day": 3.0,
                        "relay_fee": 5.0,
                        "address_return_fee": null,
                        "alt_site_fee": null,
                        "shipment_fee": 32.0,
                        "free_hub_hours": 24,
                        "currency": "CAD"
                      },
                      "created_at": "2026-09-24T14:00:00-04:00"
                    },
                    "hold": {
                      "from_tier_kg": 10,
                      "tier_kg": 20,
                      "subject_type": "luggage_hold",
                      "subject_id": 55,
                      "amount": 8.0,
                      "currency": "CAD",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/luggage-relay/8801/hold-pay?expires=1790000000&signature=…"
                    },
                    "options": {
                      "keep": false,
                      "warn_until": null,
                      "pickup_site": {
                        "choices": [],
                        "fee": 0.0,
                        "cancellable": false
                      },
                      "return_site": {
                        "changeable": false,
                        "choices": []
                      },
                      "return_time": {
                        "changeable": true,
                        "latest": "2026-10-08T17:40:00-04:00"
                      },
                      "delivery": {
                        "available": false,
                        "fee": null,
                        "chosen": false,
                        "paid": false,
                        "default_country": "CA"
                      },
                      "shipment": {
                        "available": false,
                        "channels": [
                          "label",
                          "courier"
                        ],
                        "weight_tiers_kg": [
                          5,
                          10,
                          20,
                          32
                        ],
                        "tier_required": false,
                        "chosen": true,
                        "paid": false,
                        "shipped": false
                      },
                      "resend_code": true
                    },
                    "timezone": "America/Toronto"
                  }
                }
              }
            }
          },
          "422": {
            "description": "LOCKER_STORAGE_WEIGHT_REQUIRED or an incomplete address"
          },
          "409": {
            "description": "LOCKER_STORAGE_OPTION_GONE, LOCKER_STORAGE_SHIPMENT_UNPRICED, or not changeable any more",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "LOCKER_STORAGE_ACTION_UNAVAILABLE",
                  "message": "This action is not available right now."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.storage"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-storage.shipment",
        "x-graphql": "platformAppLockerStorageShipment",
        "x-capability": "locker.storage"
      }
    },
    "/app/v1/pay/outstanding": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Everything this payer owes",
        "description": "What the badge on the app's home screen counts: every payable this payer owes across the business, without scanning anything. Runs on app open, so a resolver that cannot answer cheaply returns nothing rather than make every launch slow — a short list is therefore not proof that nothing is owed. Needs the pay.scan capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPayOutstanding",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Outstanding payables",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "count": 1,
                  "total_cents": 1250,
                  "payables": [
                    {
                      "subject_type": "locker",
                      "subject_id": 8801,
                      "amount_cents": 1250,
                      "amount": 12.5,
                      "currency": "CAD",
                      "title": "Locker storage — CAB-A",
                      "description": "3 h 20 min"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry pay.scan"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.pay.outstanding",
        "x-graphql": "platformAppPayOutstanding",
        "x-capability": "pay.scan"
      }
    },
    "/app/v1/pay/resolve": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Resolve a scanned pay tag",
        "description": "Scan-to-pay entry point. The tag token names a device and nothing else; who is standing at it comes from the authenticated session. Returns every payable this payer owes at that device — none, one, or several — and the app decides from the list length whether to say nothing is due, go straight to paying, or show a chooser. Resolving also records that the sticker was scanned, which is the only way to tell a working sticker from one that peeled off. Throttled to 30 requests a minute. Needs the pay.scan capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPayResolveTag",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag_token"
                ],
                "properties": {
                  "tag_token": {
                    "type": "string",
                    "maxLength": 64
                  }
                }
              },
              "example": {
                "tag_token": "7b1e9c04a8f24d6fb0537ce1249ad835"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What this payer owes at that device",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "tag": {
                    "token": "7b1e9c04a8f24d6fb0537ce1249ad835",
                    "label": "Cabinet A, front panel",
                    "target_type": "locker",
                    "target_id": 312
                  },
                  "payables": [
                    {
                      "subject_type": "locker",
                      "subject_id": 8801,
                      "amount_cents": 1250,
                      "amount": 12.5,
                      "currency": "CAD",
                      "title": "Locker storage — CAB-A",
                      "description": "3 h 20 min"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The sticker is revoked, unknown, or points at something this deployment cannot collect for",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "TAG_NOT_USABLE",
                  "message": "This code is no longer in use."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry pay.scan"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.pay.resolve",
        "x-graphql": "platformAppPayResolveTag",
        "x-capability": "pay.scan"
      }
    },
    "/app/v1/pay/links": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Pay the code shown on a cabinet screen",
        "description": "The payment code a smart locker screen shows when a pickup — or a relayed bag's delivery or shipment — has to be paid is a signed link to one bill (/pay/locker-storage/{rental}?expires=…&signature=…), not a sticker token. The app posts the scanned link; the signature is the authorisation, as it is in a browser, so the payer need not be the renter. Raises the payment request and answers in the request shape, ready for pay/requests/{token}/pay. A link from another business answers OTHER_BUSINESS with pay_url (also data.pay_url) for a browser. Throttled to 30 requests a minute. Requires the pay.scan capability. It also accepts a payment request's own page (/pay/r/{token}), which is what the screen shows for a shop sale: a request nobody holds yet (raised by a guest at the device) passes to the signed-in payer; one another payer holds answers REQUEST_HELD_ELSEWHERE and another business's answers OTHER_BUSINESS, both with pay_url; a paid, lapsed or unknown request answers NOTHING_TO_PAY. Needs the pay.scan capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPayResolveLink",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "link"
                ],
                "properties": {
                  "link": {
                    "type": "string",
                    "maxLength": 2048
                  }
                }
              },
              "example": {
                "link": "https://app.example.com/pay/locker-storage/8801?expires=1790000000&signature=5d1c…"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "request": {
                    "token": "3f9c2a7be51d4c08a6f1e2d3b4c5a6e7",
                    "subject_type": "locker",
                    "subject_id": 8801,
                    "amount_cents": 1250,
                    "amount": 12.5,
                    "currency": "CAD",
                    "description": "Locker storage — CAB-A · 12",
                    "status": "pending",
                    "expires_at": "2026-09-25T10:30:00-04:00",
                    "paid_at": null,
                    "pay_url": "https://app.example.com/pay/r/3f9c2a7be51d4c08a6f1e2d3b4c5a6e7"
                  },
                  "methods": [
                    {
                      "kind": "wallet",
                      "gateway": null,
                      "method": "wallet",
                      "label": "Pay with balance",
                      "completion": "redirect",
                      "available": true,
                      "reason": null
                    },
                    {
                      "kind": "gateway",
                      "gateway": "stripe",
                      "method": "card",
                      "label": "Credit / Debit Card",
                      "completion": "sheet",
                      "available": true,
                      "reason": null
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "LINK_NOT_USABLE (bad signature, expired, not a cabinet payment link), NOTHING_TO_PAY, OTHER_BUSINESS or REQUEST_HELD_ELSEWHERE (both with pay_url, also as data.pay_url)"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry pay.scan"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.pay.links",
        "x-graphql": "platformAppPayResolveLink",
        "x-capability": "pay.scan"
      }
    },
    "/app/v1/pay/requests": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Raise a payment request for one payable",
        "description": "Turns one outstanding payable into a request that can be settled. The amount is never taken from the caller: the payable is re-read from the business that owns it, so an app cannot name its own price or raise a charge against a subject it merely guessed. Passing tag_token scopes the re-read to that device; omitting it re-reads everything the payer owes. Asking twice for the same subject returns the request already standing rather than raising a second one. Throttled to 30 requests a minute. Needs the pay.scan capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPayCreateRequest",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subject_type",
                  "subject_id"
                ],
                "properties": {
                  "subject_type": {
                    "type": "string",
                    "maxLength": 32,
                    "example": "locker"
                  },
                  "subject_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "tag_token": {
                    "type": "string",
                    "maxLength": 64,
                    "nullable": true
                  }
                }
              },
              "example": {
                "subject_type": "locker",
                "subject_id": 8801,
                "tag_token": "7b1e9c04a8f24d6fb0537ce1249ad835"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request, and the methods that may settle it",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "request": {
                    "token": "9f2c41ab7d6e40518c3a0b17e5d94a26",
                    "subject_type": "locker",
                    "subject_id": 8801,
                    "amount_cents": 1250,
                    "amount": 12.5,
                    "currency": "CAD",
                    "description": "Locker storage — CAB-A",
                    "status": "pending",
                    "expires_at": "2026-09-04T18:30:00-04:00",
                    "paid_at": null,
                    "pay_url": "https://app.superroute.ca/pay/r/9f2c41ab7d6e40518c3a0b17e5d94a26"
                  },
                  "methods": [
                    {
                      "kind": "wallet",
                      "gateway": null,
                      "method": "wallet",
                      "label": "Account balance",
                      "icon": "fas fa-wallet",
                      "badge_color": "secondary",
                      "available": true,
                      "reason": null,
                      "completion": "redirect"
                    },
                    {
                      "kind": "gateway",
                      "gateway": "stripe",
                      "method": "card",
                      "label": "Credit / Debit Card",
                      "icon": "fas fa-credit-card",
                      "badge_color": "primary",
                      "completion": "sheet",
                      "available": true,
                      "reason": null
                    },
                    {
                      "kind": "gateway",
                      "gateway": "alphapay",
                      "method": "wechat_pay",
                      "label": "AlphaPay WeChat Pay",
                      "icon": "fab fa-weixin",
                      "badge_color": "success",
                      "available": true,
                      "reason": null,
                      "completion": "redirect"
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "The payer does not owe the named subject",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "NOTHING_TO_PAY",
                  "message": "You have nothing to pay here."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry pay.scan"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.pay.requests.create",
        "x-graphql": "platformAppPayCreateRequest",
        "x-capability": "pay.scan"
      }
    },
    "/app/v1/pay/requests/{publicToken}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "One payment request and its methods",
        "description": "What the request is for, what it costs, and what may settle it. The method list is the business's configured gateways narrowed by the methods it left switched on, in its own order, plus the account balance when the payer has one and it covers the amount. A method the payer cannot use is returned with available false and a reason rather than omitted, so the app can grey it out and say why. Needs the pay.scan capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPayRequest",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "publicToken",
            "in": "path",
            "required": true,
            "description": "The request's own opaque token, 32 hex characters.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{32}$",
              "example": "9f2c41ab7d6e40518c3a0b17e5d94a26"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The request and its methods",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "request": {
                    "token": "9f2c41ab7d6e40518c3a0b17e5d94a26",
                    "subject_type": "locker",
                    "subject_id": 8801,
                    "amount_cents": 1250,
                    "amount": 12.5,
                    "currency": "CAD",
                    "description": "Locker storage — CAB-A",
                    "status": "pending",
                    "expires_at": "2026-09-04T18:30:00-04:00",
                    "paid_at": null,
                    "pay_url": "https://app.superroute.ca/pay/r/9f2c41ab7d6e40518c3a0b17e5d94a26"
                  },
                  "methods": [
                    {
                      "kind": "wallet",
                      "gateway": null,
                      "method": "wallet",
                      "label": "Account balance",
                      "icon": "fas fa-wallet",
                      "badge_color": "secondary",
                      "available": true,
                      "reason": null,
                      "completion": "redirect"
                    },
                    {
                      "kind": "gateway",
                      "gateway": "stripe",
                      "method": "card",
                      "label": "Credit / Debit Card",
                      "icon": "fas fa-credit-card",
                      "badge_color": "primary",
                      "completion": "sheet",
                      "available": true,
                      "reason": null
                    },
                    {
                      "kind": "gateway",
                      "gateway": "alphapay",
                      "method": "wechat_pay",
                      "label": "AlphaPay WeChat Pay",
                      "icon": "fab fa-weixin",
                      "badge_color": "success",
                      "available": true,
                      "reason": null,
                      "completion": "redirect"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Unknown token, or it belongs to another payer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "NOT_FOUND",
                  "message": "Unknown item"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry pay.scan"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.pay.requests.show",
        "x-graphql": "platformAppPayRequest",
        "x-capability": "pay.scan"
      }
    },
    "/app/v1/pay/requests/{publicToken}/pay": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Pay a payment request",
        "description": "Start paying. A wallet payment finishes here and comes back with paid true. A gateway payment does not: it comes back with a `next` object saying how the payer finishes. `next.kind` is the only field worth branching on — `redirect` means open `next.checkout_url`, `sheet` means hand `next.client_secret` to the provider's mobile SDK, initialised with `next.publishable_key`. The sheet is where Apple Pay and Google Pay appear: they are not separate methods to switch on beside card, they are surfaces the SDK offers on that same payment when the device supports them. Either way the money is not collected until the gateway says so — poll the request until its status becomes paid. Pass method wallet with no gateway to spend the balance; otherwise pass the gateway code and the method it offers. Throttled to 10 requests a minute: it moves money, or calls out to somebody who does. Needs the pay.scan capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppPay",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "publicToken",
            "in": "path",
            "required": true,
            "description": "The request's own opaque token, 32 hex characters.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{32}$",
              "example": "9f2c41ab7d6e40518c3a0b17e5d94a26"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "method"
                ],
                "properties": {
                  "method": {
                    "type": "string",
                    "maxLength": 32,
                    "example": "wallet"
                  },
                  "gateway": {
                    "type": "string",
                    "maxLength": 32,
                    "nullable": true,
                    "example": "alphapay"
                  }
                }
              },
              "example": {
                "method": "wallet"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settled from the balance, or told how to finish (redirect or native sheet)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "paid": true,
                  "request": {
                    "token": "9f2c41ab7d6e40518c3a0b17e5d94a26",
                    "subject_type": "locker",
                    "subject_id": 8801,
                    "amount_cents": 1250,
                    "amount": 12.5,
                    "currency": "CAD",
                    "description": "Locker storage — CAB-A",
                    "status": "paid",
                    "expires_at": "2026-09-04T18:30:00-04:00",
                    "paid_at": "2026-09-04T18:12:07-04:00",
                    "pay_url": "https://app.superroute.ca/pay/r/9f2c41ab7d6e40518c3a0b17e5d94a26"
                  },
                  "methods": [
                    {
                      "kind": "wallet",
                      "gateway": null,
                      "method": "wallet",
                      "label": "Account balance",
                      "icon": "fas fa-wallet",
                      "badge_color": "secondary",
                      "available": true,
                      "reason": null,
                      "completion": "redirect"
                    },
                    {
                      "kind": "gateway",
                      "gateway": "stripe",
                      "method": "card",
                      "label": "Credit / Debit Card",
                      "icon": "fas fa-credit-card",
                      "badge_color": "primary",
                      "completion": "sheet",
                      "available": true,
                      "reason": null
                    },
                    {
                      "kind": "gateway",
                      "gateway": "alphapay",
                      "method": "wechat_pay",
                      "label": "AlphaPay WeChat Pay",
                      "icon": "fab fa-weixin",
                      "badge_color": "success",
                      "available": true,
                      "reason": null,
                      "completion": "redirect"
                    }
                  ],
                  "next": {
                    "kind": "sheet",
                    "checkout_url": null,
                    "client_secret": "pi_3Qx0example_secret_9fA2",
                    "publishable_key": "pk_live_51Hxxxxxx",
                    "merchant_country": "CA",
                    "merchant_display_name": "Waypoint Logistics"
                  }
                }
              }
            }
          },
          "422": {
            "description": "Expired, refused, or a gateway that cannot be used here",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "CHARGE_FAILED",
                  "message": "The payment could not be completed. Please try again."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry pay.scan"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.pay.requests.pay",
        "x-graphql": "platformAppPay",
        "x-capability": "pay.scan"
      }
    },
    "/app/v1/storefront": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Storefront entry",
        "description": "Signed in (bearer token of the app session). Which home cards the app shows (A3, A4): `mall` (null when the platform gave the client no mall or the client has no marketplace) with `operations_enabled` (false = the mall is its store directory only), `stores_available` (listed stores exist), `group_buy_available` (the app's group_buy capability is on and a group buy can be ordered now). Never 404 for a known client: a client without the marketplace answers all off. Answered exactly as the internal route.",
        "operationId": "platformAppStorefront",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "mall": {
                      "enabled": true,
                      "operations_enabled": true,
                      "name": "Client",
                      "web_url": "https://shop.example.com/mall"
                    },
                    "stores_available": true,
                    "group_buy_available": true,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.storefront",
        "x-graphql": "platformAppStorefront"
      }
    },
    "/app/v1/mall/home": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mall home blocks",
        "description": "Signed in (bearer token of the app session). The blocks the client shows on the mall home, in the client's order: `banners`, `categories`, `group_buys`, `coupons`, `featured_stores`, `featured_products`, `stores` (first 12 of the directory). An empty block is left out; `group_buys` is left out when the app's group_buy capability is off. Without mall operations or without a mall: `directory_only: true` and no blocks — show mall/stores. 404 STOREFRONT_UNAVAILABLE when the client has no marketplace. Every product card carries currency: the currency code its prices are in (the store's Client's). Answered exactly as the internal route.",
        "operationId": "platformAppMallHome",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "directory_only": false,
                    "blocks": [
                      {
                        "key": "categories",
                        "items": [
                          {
                            "id": 1,
                            "name": "Food",
                            "children": [
                              {
                                "id": 2,
                                "name": "Pizza"
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "key": "group_buys",
                        "items": [
                          {
                            "code": "PZBOX7",
                            "title": "Friday pizza box",
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "opens_at": "2026-10-14T14:00:00-04:00",
                            "cutoff_at": "2026-10-16T15:00:00-04:00",
                            "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                          }
                        ]
                      },
                      {
                        "key": "coupons",
                        "items": [
                          {
                            "id": 1,
                            "name": "5 off your first order",
                            "description": "Orders over 30",
                            "code": "WELCOME5",
                            "ends_on": "2026-12-31"
                          }
                        ]
                      },
                      {
                        "key": "featured_stores",
                        "items": [
                          {
                            "id": 1,
                            "slug": "pizza-place-1",
                            "name": "Pizza Place",
                            "description": "",
                            "store_type": "restaurant",
                            "store_type_label": "Restaurant",
                            "tags": [
                              "pizza",
                              "halal"
                            ],
                            "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                            "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                            "rating_avg": 4.6,
                            "rating_count": 38,
                            "address": "12 King St W",
                            "city": "Toronto"
                          }
                        ]
                      },
                      {
                        "key": "featured_products",
                        "items": [
                          {
                            "id": 1,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Margherita",
                            "description": "Tomato, mozzarella, basil",
                            "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                            "price": 12,
                            "list_price": 14,
                            "compare_at_price": 14,
                            "on_sale": true,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [
                              {
                                "code": "gluten",
                                "label": "Gluten"
                              },
                              {
                                "code": "milk",
                                "label": "Milk"
                              }
                            ],
                            "affiliate": false,
                            "external_url": null
                          }
                        ]
                      },
                      {
                        "key": "stores",
                        "items": [
                          {
                            "id": 1,
                            "slug": "pizza-place-1",
                            "name": "Pizza Place",
                            "description": "",
                            "store_type": "restaurant",
                            "store_type_label": "Restaurant",
                            "tags": [
                              "pizza",
                              "halal"
                            ],
                            "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                            "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                            "rating_avg": 4.6,
                            "rating_count": 38,
                            "address": "12 King St W",
                            "city": "Toronto"
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "STOREFRONT_UNAVAILABLE"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.mall.home",
        "x-graphql": "platformAppMallHome"
      }
    },
    "/app/v1/mall/stores": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store directory",
        "description": "Signed in (bearer token of the app session). Every listed store in the mall (every listed store of the client when it has no mall), in the client's order then by rating; filters by store type, tag (case-insensitive) and words (name, names in other languages, tags); 24 a page. `facets` lists the types and tags with their store counts, computed over all stores. Answered exactly as the internal route.",
        "operationId": "platformAppMallStores",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Store type, e.g. restaurant"
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "One store tag"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Words, at most 100 characters"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "stores": [
                      {
                        "id": 1,
                        "slug": "pizza-place-1",
                        "name": "Pizza Place",
                        "description": "",
                        "store_type": "restaurant",
                        "store_type_label": "Restaurant",
                        "tags": [
                          "pizza",
                          "halal"
                        ],
                        "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                        "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                        "rating_avg": 4.6,
                        "rating_count": 38,
                        "address": "12 King St W",
                        "city": "Toronto"
                      }
                    ],
                    "facets": {
                      "types": [
                        {
                          "type": "restaurant",
                          "label": "Restaurant",
                          "count": 1
                        }
                      ],
                      "tags": [
                        {
                          "tag": "pizza",
                          "count": 1
                        },
                        {
                          "tag": "halal",
                          "count": 1
                        }
                      ]
                    },
                    "filters": {
                      "type": "",
                      "tag": "pizza",
                      "q": ""
                    },
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 24,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "STOREFRONT_UNAVAILABLE"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.mall.stores",
        "x-graphql": "platformAppMallStores"
      }
    },
    "/app/v1/mall/search": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mall search",
        "description": "Signed in (bearer token of the app session). Stores whose name, other-language names or tags contain the words, and listed products whose name contains them, grouped by store (at most 60 products). Empty words: empty lists. Needs a mall with operations: 404 MALL_UNAVAILABLE otherwise. Every product card carries currency: the currency code its prices are in (the store's Client's). Answered exactly as the internal route.",
        "operationId": "platformAppMallSearch",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "marg"
            },
            "description": "Words, at most 100 characters"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "q": "marg",
                    "stores": [],
                    "products_by_store": [
                      {
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place",
                          "description": "",
                          "store_type": "restaurant",
                          "store_type_label": "Restaurant",
                          "tags": [
                            "pizza",
                            "halal"
                          ],
                          "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                          "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                          "rating_avg": 4.6,
                          "rating_count": 38,
                          "address": "12 King St W",
                          "city": "Toronto"
                        },
                        "products": [
                          {
                            "id": 1,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Margherita",
                            "description": "Tomato, mozzarella, basil",
                            "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                            "price": 12,
                            "list_price": 14,
                            "compare_at_price": 14,
                            "on_sale": true,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [
                              {
                                "code": "gluten",
                                "label": "Gluten"
                              },
                              {
                                "code": "milk",
                                "label": "Milk"
                              }
                            ],
                            "affiliate": false,
                            "external_url": null
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "STOREFRONT_UNAVAILABLE | MALL_UNAVAILABLE"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.mall.search",
        "x-graphql": "platformAppMallSearch"
      }
    },
    "/app/v1/mall/categories/{categoryId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mall category products",
        "description": "Signed in (bearer token of the app session). One active mall category (a top category includes its sub-categories) and one page of its products, 24 a page, each with its own store. Needs a mall with operations. Every product card carries currency: the currency code its prices are in (the store's Client's). Answered exactly as the internal route.",
        "operationId": "platformAppMallCategory",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "categoryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "category": {
                      "id": 1,
                      "name": "Food",
                      "children": [
                        {
                          "id": 2,
                          "name": "Pizza"
                        }
                      ],
                      "parent": null
                    },
                    "products": [
                      {
                        "id": 1,
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "name": "Margherita",
                        "description": "Tomato, mozzarella, basil",
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                        "price": 12,
                        "list_price": 14,
                        "compare_at_price": 14,
                        "on_sale": true,
                        "currency": "CAD",
                        "available": true,
                        "within_mealtimes": true,
                        "mealtimes": [],
                        "allergens": [
                          {
                            "code": "gluten",
                            "label": "Gluten"
                          },
                          {
                            "code": "milk",
                            "label": "Milk"
                          }
                        ],
                        "affiliate": false,
                        "external_url": null
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 24,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "STOREFRONT_UNAVAILABLE | MALL_UNAVAILABLE | MALL_CATEGORY_NOT_FOUND"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.mall.category",
        "x-graphql": "platformAppMallCategory"
      }
    },
    "/app/v1/mall/group-buys": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Group buy channel",
        "description": "Signed in (bearer token of the app session). The group buys buyers may order now, soonest cutoff first; each `url` opens its page on the client's white-label host. In a mall with operations `category` narrows them to those carrying a product of that mall category and `categories` is the tree to choose from; otherwise the group buys of every listed store and no categories. Empty when the app's group_buy capability is off. Answered exactly as the internal route.",
        "operationId": "platformAppMallGroupBuys",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Mall category id"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "group_buys": [
                      {
                        "code": "PZBOX7",
                        "title": "Friday pizza box",
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "opens_at": "2026-10-14T14:00:00-04:00",
                        "cutoff_at": "2026-10-16T15:00:00-04:00",
                        "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                      }
                    ],
                    "categories": [
                      {
                        "id": 1,
                        "name": "Food",
                        "children": [
                          {
                            "id": 2,
                            "name": "Pizza"
                          }
                        ]
                      }
                    ],
                    "category_id": 0
                  }
                }
              }
            }
          },
          "404": {
            "description": "STOREFRONT_UNAVAILABLE"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.mall.group-buys",
        "x-graphql": "platformAppMallGroupBuys"
      }
    },
    "/app/v1/stores/{slug}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store page",
        "description": "Signed in (bearer token of the app session). A listed store of the client (also one that is not in the mall): profile, whether it takes orders now (`accepting_orders`, `intake_blockers`), the order types it can take with ASAP and the time slots (store clock, `timezone`), categories, the menu as `sections` (category order; products of no active category last, `label` null) with each item's price, stock state and option groups (each group and value with `image_url`, null without an image), the featured row and banners (unfiltered view only), its group buys and the 10 newest approved reviews. `q`, `cat` (with its sub-categories) and `sort` filter the menu like the web. `table` enters the dine-in context: `dine_in.table_code` is set and only dine_in is offered; an unknown table, or a store without dine-in, answers 404 TABLE_NOT_FOUND. Without `table`, dine_in is never listed. Every product card carries currency: the currency code its prices are in (the store's Client's). Added (docs/STORE-STYLES-DESIGN.md P2): design {style simple|multi_page — the style this answer is drawn in (a table always gets simple), published_version (0 = never published; the store then looks as before), nav_categories[{id, name}], top_blocks — in the simple style, the blocks above the menu on the unfiltered view of a store that published a design; banners, announcement and featured stay in the answer as before}. In the multi-page style the app opens /home, /categories/{categoryId} and the product page's page_blocks. Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Answered exactly as the internal route.",
        "operationId": "platformAppStore",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Words in the item name"
          },
          {
            "name": "cat",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Store category id"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "price_asc",
                "price_desc",
                "name",
                "newest"
              ]
            }
          },
          {
            "name": "table",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "T12"
            },
            "description": "Table code from the table QR (/s/{slug}/t/{table})"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place",
                      "description": "",
                      "store_type": "restaurant",
                      "store_type_label": "Restaurant",
                      "tags": [
                        "pizza",
                        "halal"
                      ],
                      "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                      "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                      "rating_avg": 4.6,
                      "rating_count": 38,
                      "address": "12 King St W",
                      "city": "Toronto",
                      "phone": "",
                      "min_order_amount": 15,
                      "prep_time_minutes": 20,
                      "timezone": "America/Toronto",
                      "announcement": "",
                      "social_links": {
                        "instagram": "https://instagram.com/pizzaplace"
                      },
                      "food": true,
                      "guest_orders": true,
                      "currency": "CAD",
                      "web_url": "https://shop.example.com/s/pizza-place-1"
                    },
                    "accepting_orders": true,
                    "intake_blockers": [],
                    "order_types": [
                      {
                        "type": "collection",
                        "label": "Pick-up",
                        "accepting": true,
                        "asap": true,
                        "days": [
                          {
                            "date": "2026-10-14",
                            "slots": [
                              "15:30",
                              "15:45",
                              "16:00"
                            ]
                          }
                        ]
                      }
                    ],
                    "dine_in": null,
                    "banners": [
                      {
                        "image_url": "https://shop.example.com/storage/stores/31/banner.jpg",
                        "link": "https://shop.example.com/s/pizza-place-1/i/1"
                      }
                    ],
                    "categories": [
                      {
                        "id": 1,
                        "parent_id": null,
                        "name": "Pizzas"
                      }
                    ],
                    "sections": [
                      {
                        "category_id": 1,
                        "label": "Pizzas",
                        "items": [
                          {
                            "id": 1,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Margherita",
                            "description": "Tomato, mozzarella, basil",
                            "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                            "price": 12,
                            "list_price": 14,
                            "compare_at_price": 14,
                            "on_sale": true,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [
                              {
                                "code": "gluten",
                                "label": "Gluten"
                              },
                              {
                                "code": "milk",
                                "label": "Milk"
                              }
                            ],
                            "affiliate": false,
                            "external_url": null,
                            "option_groups": [
                              {
                                "id": 1,
                                "label": "Size",
                                "type": "radio",
                                "required": true,
                                "min": 0,
                                "max": null,
                                "image_url": null,
                                "values": [
                                  {
                                    "id": 1,
                                    "label": "12 inch",
                                    "delta": 0,
                                    "default": false,
                                    "image_url": null
                                  },
                                  {
                                    "id": 2,
                                    "label": "16 inch",
                                    "delta": 4,
                                    "default": false,
                                    "image_url": null
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "category_id": null,
                        "label": null,
                        "items": [
                          {
                            "id": 2,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Cola",
                            "description": "",
                            "image_url": null,
                            "price": 2.5,
                            "list_price": 2.5,
                            "compare_at_price": null,
                            "on_sale": false,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [],
                            "affiliate": false,
                            "external_url": null,
                            "option_groups": []
                          }
                        ]
                      }
                    ],
                    "featured": [
                      {
                        "id": 1,
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "name": "Margherita",
                        "description": "Tomato, mozzarella, basil",
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                        "price": 12,
                        "list_price": 14,
                        "compare_at_price": 14,
                        "on_sale": true,
                        "currency": "CAD",
                        "available": true,
                        "within_mealtimes": true,
                        "mealtimes": [],
                        "allergens": [
                          {
                            "code": "gluten",
                            "label": "Gluten"
                          },
                          {
                            "code": "milk",
                            "label": "Milk"
                          }
                        ],
                        "affiliate": false,
                        "external_url": null,
                        "option_groups": [
                          {
                            "id": 1,
                            "label": "Size",
                            "type": "radio",
                            "required": true,
                            "min": 0,
                            "max": null,
                            "image_url": null,
                            "values": [
                              {
                                "id": 1,
                                "label": "12 inch",
                                "delta": 0,
                                "default": false,
                                "image_url": null
                              },
                              {
                                "id": 2,
                                "label": "16 inch",
                                "delta": 4,
                                "default": false,
                                "image_url": null
                              }
                            ]
                          }
                        ]
                      }
                    ],
                    "group_buys": [
                      {
                        "code": "PZBOX7",
                        "title": "Friday pizza box",
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "opens_at": "2026-10-14T14:00:00-04:00",
                        "cutoff_at": "2026-10-16T15:00:00-04:00",
                        "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                      }
                    ],
                    "reviews": [
                      {
                        "rating": 5,
                        "comment": "Great crust",
                        "reviewer": null,
                        "merchant_reply": "Thank you!",
                        "created_at": "2026-10-14T15:00:00-04:00"
                      }
                    ],
                    "filters": {
                      "q": "",
                      "sort": "",
                      "cat": 0
                    },
                    "design": {
                      "style": "simple",
                      "published_version": 2,
                      "nav_categories": [
                        {
                          "id": 5,
                          "name": "Kitchen"
                        }
                      ],
                      "top_blocks": [
                        {
                          "id": "b9a8b7c6d5",
                          "type": "announcement",
                          "settings": {
                            "tone": "accent"
                          },
                          "data": {
                            "text": "Closed on Monday"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "STORE_NOT_FOUND | TABLE_NOT_FOUND"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.stores.show",
        "x-graphql": "platformAppStore"
      }
    },
    "/app/v1/stores/{slug}/home": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store home page (multi-page style)",
        "description": "Signed in (bearer token of the app session). The home page of a store in the multi-page style (docs/STORE-STYLES-DESIGN.md P2): the store card, accepting_orders, design {style, published_version, nav_categories[{id, name}] — the top-level categories for the category bar} and blocks in the order the merchant published. A store in the simple style answers 404 STORE_PAGE_NOT_FOUND (its home is the store page); an unknown store 404 STORE_NOT_FOUND. Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Answered exactly as the internal route.",
        "operationId": "platformAppStoreHome",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "home-goods-1"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "home-goods-1",
                      "name": "Home Goods",
                      "description": "",
                      "store_type": "retail",
                      "store_type_label": "Retail Store",
                      "tags": [],
                      "logo_url": null,
                      "cover_url": null,
                      "rating_avg": 0,
                      "rating_count": 0,
                      "address": "1 Main St",
                      "city": "Toronto",
                      "currency": "CAD",
                      "web_url": "https://shop.example.com/s/home-goods-1"
                    },
                    "accepting_orders": true,
                    "design": {
                      "style": "multi_page",
                      "published_version": 3,
                      "nav_categories": [
                        {
                          "id": 5,
                          "name": "Kitchen"
                        },
                        {
                          "id": 7,
                          "name": "Garden"
                        }
                      ]
                    },
                    "blocks": [
                      {
                        "id": "b1a2b3c4d5",
                        "type": "banner",
                        "settings": {
                          "height": "medium",
                          "autoplay": true
                        },
                        "data": {
                          "slides": [
                            {
                              "image_url": "https://shop.example.com/storage/merchant_stores/1/banner_1.jpg",
                              "link": "https://shop.example.com/s/home-goods-1/c/5"
                            }
                          ]
                        }
                      },
                      {
                        "id": "b2b3c4d5e6",
                        "type": "category_entry",
                        "settings": {
                          "columns": 4,
                          "display": "image"
                        },
                        "data": {
                          "title": "Categories",
                          "categories": [
                            {
                              "id": 5,
                              "name": "Kitchen",
                              "image_url": null
                            },
                            {
                              "id": 7,
                              "name": "Garden",
                              "image_url": null
                            }
                          ]
                        }
                      },
                      {
                        "id": "b3c4d5e6f7",
                        "type": "product_grid",
                        "settings": {
                          "limit": 8,
                          "columns": 4,
                          "layout": "grid"
                        },
                        "data": {
                          "title": "New arrivals",
                          "products": [
                            {
                              "id": 12,
                              "store": {
                                "id": 1,
                                "slug": "home-goods-1",
                                "name": "Home Goods"
                              },
                              "name": "Copper pan",
                              "description": "",
                              "image_url": "https://shop.example.com/storage/products/12/pan.jpg",
                              "price": 40,
                              "list_price": 40,
                              "compare_at_price": null,
                              "on_sale": false,
                              "currency": "CAD",
                              "available": true,
                              "within_mealtimes": true,
                              "mealtimes": [],
                              "allergens": [],
                              "affiliate": false,
                              "external_url": null
                            }
                          ]
                        }
                      },
                      {
                        "id": "b4d5e6f7a8",
                        "type": "image_text",
                        "settings": {
                          "image_position": "left"
                        },
                        "data": {
                          "image_url": "https://shop.example.com/storage/merchant_stores/1/banner_2.jpg",
                          "title": "Our story",
                          "body": "Made by hand since 1990",
                          "link": "",
                          "button_text": ""
                        }
                      },
                      {
                        "id": "b5e6f7a8b9",
                        "type": "video",
                        "settings": {
                          "autoplay": false
                        },
                        "data": {
                          "title": "",
                          "kind": "embed",
                          "url": "https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_PAGE_NOT_FOUND",
                  "message": "This store does not use the multi-page style."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.stores.home",
        "x-graphql": "platformAppStoreHome"
      }
    },
    "/app/v1/stores/{slug}/categories/{categoryId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store category page (multi-page style)",
        "description": "Signed in (bearer token of the app session). A category page of a store in the multi-page style (docs/STORE-STYLES-DESIGN.md P2): store, category {id, parent_id, name}, accepting_orders, design (as the home page) and blocks — the category's own layout when it has one, else the store's; the product_list block holds the category's items and its sub-categories', paged and filtered by sort (price_asc, price_desc, name, newest), sub (a direct sub-category), in_stock and page. 404 STORE_PAGE_NOT_FOUND in the simple style, CATEGORY_NOT_FOUND for a category the store does not have (or has switched off). Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Answered exactly as the internal route.",
        "operationId": "platformAppStoreCategory",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "home-goods-1"
            }
          },
          {
            "name": "categoryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 5
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "price_asc",
                "price_desc",
                "name",
                "newest"
              ]
            }
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "A direct sub-category id"
          },
          {
            "name": "in_stock",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "home-goods-1",
                      "name": "Home Goods"
                    },
                    "category": {
                      "id": 5,
                      "parent_id": null,
                      "name": "Kitchen"
                    },
                    "accepting_orders": true,
                    "design": {
                      "style": "multi_page",
                      "published_version": 3,
                      "nav_categories": [
                        {
                          "id": 5,
                          "name": "Kitchen"
                        },
                        {
                          "id": 7,
                          "name": "Garden"
                        }
                      ]
                    },
                    "blocks": [
                      {
                        "id": "c1d2e3f4a5",
                        "type": "category_header",
                        "settings": {
                          "show_image": true,
                          "show_description": true
                        },
                        "data": {
                          "name": "Kitchen",
                          "image_url": null,
                          "description": "Pots, pans and knives"
                        }
                      },
                      {
                        "id": "c2d3e4f5a6",
                        "type": "product_list",
                        "settings": {
                          "page_size": 24,
                          "columns": 4,
                          "show_filters": true
                        },
                        "data": {
                          "items": [
                            {
                              "id": 12,
                              "store": {
                                "id": 1,
                                "slug": "home-goods-1",
                                "name": "Home Goods"
                              },
                              "name": "Copper pan",
                              "description": "",
                              "image_url": "https://shop.example.com/storage/products/12/pan.jpg",
                              "price": 40,
                              "list_price": 40,
                              "compare_at_price": null,
                              "on_sale": false,
                              "currency": "CAD",
                              "available": true,
                              "within_mealtimes": true,
                              "mealtimes": [],
                              "allergens": [],
                              "affiliate": false,
                              "external_url": null
                            }
                          ],
                          "pagination": {
                            "current_page": 1,
                            "last_page": 1,
                            "per_page": 24,
                            "total": 1,
                            "has_more": false
                          },
                          "subcategories": [
                            {
                              "id": 6,
                              "name": "Knives"
                            }
                          ],
                          "filters": {
                            "q": "",
                            "sort": "",
                            "sub": 0,
                            "in_stock": false
                          }
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_PAGE_NOT_FOUND",
                  "message": "This store does not use the multi-page style."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.stores.category",
        "x-graphql": "platformAppStoreCategory"
      }
    },
    "/app/v1/stores/{slug}/products/{productId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Product page",
        "description": "Signed in (bearer token of the app session). One product on sale in the store: the card fields plus `sku`, all `images`, active `variants` with their storefront price, `option_groups` (each group and value with `image_url`, null without an image), `group_buy` (lowest group price while an orderable campaign carries it, else null), the 20 newest approved reviews and up to 6 related products of the same category. Every product card carries currency: the currency code its prices are in (the store's Client's). Added (docs/STORE-STYLES-DESIGN.md P2): page_blocks — in the multi-page style, the product page's blocks in order (the product's own layout, else the store's; buy_box marks where this answer's purchase area goes); null in the simple style. Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Added: share — how the store lets buyers share this product, null while it offers none: {url (the product's web page, on the client's white-label host when it has one), title, channels (the store's choice in display order, each one of system, wechat, whatsapp, facebook, x, telegram, line, linkedin, reddit, pinterest, threads, tumblr, viber, weibo, qq, sms, email, copy, qr; system = the phone's own share menu, wechat = WeChat, which has no share address: copy the url and open WeChat (weixin://) on a phone, show the url as a QR code to scan with WeChat elsewhere, copy = copy the url, qr = show the url as a QR code), links (channel => address to open, for the chosen network, sms and email channels)}. Skip a channel the app does not know. Show only the listed channels. Answered exactly as the internal route.",
        "operationId": "platformAppStoreProduct",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Added (docs/SKU-STRUCTURES-DESIGN.md SX3, SX11): custom_fields [{key, label, value}] — the merchant's custom SKU fields shown to buyers that hold a value, labelled in the request's language (an option shows its label in that language when it has one) — only when there is one; otherwise the answer is as before. Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 1,
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "name": "Margherita",
                    "description": "Tomato, mozzarella, basil",
                    "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                    "price": 12,
                    "list_price": 14,
                    "compare_at_price": 14,
                    "on_sale": true,
                    "currency": "CAD",
                    "available": true,
                    "within_mealtimes": true,
                    "mealtimes": [],
                    "allergens": [
                      {
                        "code": "gluten",
                        "label": "Gluten"
                      },
                      {
                        "code": "milk",
                        "label": "Milk"
                      }
                    ],
                    "affiliate": false,
                    "external_url": null,
                    "option_groups": [
                      {
                        "id": 1,
                        "label": "Size",
                        "type": "radio",
                        "required": true,
                        "min": 0,
                        "max": null,
                        "image_url": null,
                        "values": [
                          {
                            "id": 1,
                            "label": "12 inch",
                            "delta": 0,
                            "default": false,
                            "image_url": null
                          },
                          {
                            "id": 2,
                            "label": "16 inch",
                            "delta": 4,
                            "default": false,
                            "image_url": null
                          }
                        ]
                      }
                    ],
                    "sku": "MARGHERITA",
                    "images": [
                      "https://shop.example.com/storage/products/88/margherita.jpg"
                    ],
                    "variants": [],
                    "accepting_orders": true,
                    "group_buy": {
                      "price": 10.5,
                      "code": "PZBOX7",
                      "title": "Friday pizza box",
                      "cutoff_at": "2026-10-16T15:00:00-04:00",
                      "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                    },
                    "reviews": [
                      {
                        "rating": 5,
                        "comment": "Best in town",
                        "created_at": "2026-10-14T15:00:00-04:00"
                      }
                    ],
                    "related": [],
                    "share": {
                      "url": "https://shop.example.com/s/pizza-place-1/i/1",
                      "title": "Margherita",
                      "channels": [
                        "system",
                        "whatsapp",
                        "facebook",
                        "copy",
                        "qr"
                      ],
                      "links": {
                        "whatsapp": "https://wa.me/?text=Margherita%20https%3A%2F%2Fshop.example.com%2Fs%2Fpizza-place-1%2Fi%2F1",
                        "facebook": "https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fshop.example.com%2Fs%2Fpizza-place-1%2Fi%2F1"
                      }
                    },
                    "page_blocks": [
                      {
                        "id": "p1a2b3c4d5",
                        "type": "buy_box",
                        "settings": {
                          "show_thumbnails": true
                        },
                        "data": {}
                      },
                      {
                        "id": "p2b3c4d5e6",
                        "type": "details",
                        "settings": {},
                        "data": {
                          "title": "Details",
                          "body": "Heavy copper pan",
                          "image_urls": []
                        }
                      },
                      {
                        "id": "p3c4d5e6f7",
                        "type": "related",
                        "settings": {
                          "limit": 6
                        },
                        "data": {
                          "title": "Related products",
                          "products": [
                            {
                              "id": 12,
                              "store": {
                                "id": 1,
                                "slug": "home-goods-1",
                                "name": "Home Goods"
                              },
                              "name": "Copper pan",
                              "description": "",
                              "image_url": "https://shop.example.com/storage/products/12/pan.jpg",
                              "price": 40,
                              "list_price": 40,
                              "compare_at_price": null,
                              "on_sale": false,
                              "currency": "CAD",
                              "available": true,
                              "within_mealtimes": true,
                              "mealtimes": [],
                              "allergens": [],
                              "affiliate": false,
                              "external_url": null
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "STORE_NOT_FOUND | PRODUCT_NOT_FOUND"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.stores.product",
        "x-graphql": "platformAppStoreProduct"
      }
    },
    "/app/v1/stores/{slug}/cart": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Cart of one store",
        "description": "Signed in (bearer token of the app session). The buyer's cart in this store (empty when there is none). Signed in: the linked identity's cart — the same cart as on the web — or, for an account without a linked identity, the account's own cart. Guest: the cart of X-Guest-Cart-Token; `guest_cart_token` echoes the token in use (null without one). Line prices are display prices; checkout prices again. Answered exactly as the internal route.",
        "operationId": "platformAppStoreCart",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "404": {
            "description": "STORE_NOT_FOUND"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.stores.cart",
        "x-graphql": "platformAppStoreCart"
      }
    },
    "/app/v1/stores/{slug}/cart/items": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Add to cart",
        "description": "Signed in (bearer token of the app session). Put a product in the cart with the web rules: the store takes orders now (only dine-in when `table` names a table), the product is on sale, in stock and inside its mealtimes, a product with variants names its `product_variant_id`, and `options` keep the item's option rules ({product_options.id: [store_option_value_id, ...]}, the ids from option_groups[].id and values[].id). An identical line (product, variant, options) grows. A guest's first write issues the guest cart token: keep it (body `guest_cart_token` and response header X-Guest-Cart-Token) and send it with every later cart call. Answered exactly as the internal route.",
        "operationId": "platformAppStoreCartAdd",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product_id",
                  "qty"
                ],
                "properties": {
                  "product_id": {
                    "type": "integer",
                    "example": 1
                  },
                  "product_variant_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "qty": {
                    "type": "integer",
                    "minimum": 1,
                    "example": 2
                  },
                  "options": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      }
                    },
                    "example": {
                      "1": [
                        2
                      ]
                    }
                  },
                  "table": {
                    "type": "string",
                    "example": "T12"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "404": {
            "description": "STORE_NOT_FOUND | TABLE_NOT_FOUND"
          },
          "422": {
            "description": "VALIDATION_FAILED (with errors) | STORE_CLOSED | ITEM_UNAVAILABLE (a guest answer carries guest_cart_token)"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.stores.cart.add",
        "x-graphql": "platformAppStoreCartAdd"
      }
    },
    "/app/v1/stores/{slug}/cart/items/{itemId}": {
      "patch": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Change a cart line quantity",
        "description": "Signed in (bearer token of the app session). Set the quantity of one line (items[].id); 0 removes it. A line that is not in this buyer's cart changes nothing and the cart is answered. Answered exactly as the internal route.",
        "operationId": "platformAppStoreCartUpdate",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "qty"
                ],
                "properties": {
                  "qty": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "404": {
            "description": "STORE_NOT_FOUND"
          },
          "422": {
            "description": "VALIDATION_FAILED"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.stores.cart.update",
        "x-graphql": "platformAppStoreCartUpdate"
      },
      "delete": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Remove a cart line",
        "description": "Signed in (bearer token of the app session). Remove one line (items[].id). A line that is not in this buyer's cart changes nothing and the cart is answered. Answered exactly as the internal route.",
        "operationId": "platformAppStoreCartRemove",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "404": {
            "description": "STORE_NOT_FOUND"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "APP_ACCESS_DENIED: the account does not belong to this client in this app"
          }
        },
        "x-route-name": "openapp.stores.cart.remove",
        "x-graphql": "platformAppStoreCartRemove"
      }
    },
    "/app/v1/stores/{slug}/checkout/quote": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Price the cart of a store for the order the buyer is about to place",
        "description": "Price the cart of a store for the order the buyer is about to place: totals, errors, order types, payment methods, slots, locker cabinets. The cart is the identity cart of a linked account, otherwise the account's own. table_code puts the order at that table (dine-in only). Errors: 404 STORE_NOT_FOUND, 422 CART_EMPTY, 422 TABLE_NOT_FOUND, 422 VALIDATION_FAILED. payment_methods lists wallet (after the store's own methods) for a signed-in account in a store whose payments the client collects; wallet then holds {balance, covers}: the account's available balance and whether it covers the total, otherwise wallet is null (docs/STORE-PAYMENT-COLLECTION-DESIGN.md). Answered exactly as the internal route.",
        "operationId": "platformAppStoreCheckoutQuote",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "bistro"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "ok": true,
                    "errors": [],
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "min_order": 0.0,
                    "total": 29.0,
                    "tax": 0.0,
                    "price_changed": false,
                    "currency": "CAD",
                    "order_type": "delivery",
                    "table_code": null,
                    "order_types": [
                      "delivery",
                      "collection",
                      "dine_in"
                    ],
                    "payment_methods": [
                      "stripe",
                      "wallet"
                    ],
                    "wallet": {
                      "balance": 50.0,
                      "covers": true
                    },
                    "slots": {
                      "delivery": {
                        "asap": true,
                        "days": [
                          {
                            "date": "2026-10-14",
                            "slots": [
                              "13:00",
                              "13:30"
                            ]
                          }
                        ]
                      }
                    },
                    "locker_cabinets": [],
                    "tab": null,
                    "login_required": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "order_type": {
                    "type": "string"
                  },
                  "latitude": {
                    "type": "number"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "postcode": {
                    "type": "string"
                  },
                  "requested_at": {
                    "type": "string"
                  },
                  "tip": {
                    "type": "number"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "shelf_id": {
                    "type": "integer"
                  },
                  "table_code": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "order_type": "delivery",
                "postcode": "H2X 2Z2"
              }
            }
          }
        },
        "x-route-name": "openapp.store.checkout.quote",
        "x-graphql": "platformAppStoreCheckoutQuote"
      }
    },
    "/app/v1/stores/{slug}/checkout/place": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Place the order from the cart",
        "description": "Place the order from the cart; answers the order and the payment (stripe PaymentIntent client secret, offline or tab). payment.method stripe: present the PaymentSheet with client_secret / publishable_key / merchant_country / merchant_display_name, then call confirm-payment; offline and tab: nothing to pay in the app; wallet: paid from the account's balance at once (payment.method wallet, the order already paid), only where the quote listed wallet. Errors: 404 STORE_NOT_FOUND, 422 CART_EMPTY, 403 LOGIN_REQUIRED (guest where the store takes no guest orders), 422 ORDER_TYPE_UNAVAILABLE, 422 TABLE_REQUIRED, 422 TABLE_NOT_FOUND, 422 CHECKOUT_VALIDATION_FAILED with errors[] (price_changed, out_of_delivery_area, store_closed, item_unavailable, cabinet_required, invalid_time_slot, below_min_order, ...), 422 PAYMENT_METHOD_UNAVAILABLE (also wallet where the store does not take the balance, refused before any order), 422 PAYMENT_ERROR (also a balance that does not cover the total, refused before any order), 500 CHECKOUT_FAILED, 422 VALIDATION_FAILED. CHECKOUT_VALIDATION_FAILED also carries reasons: an object {code: message} with the same codes as errors, each with the message the web checkout shows for it in the answer language (an unforeseen code gets the general message); errors stays the list of codes. Answered exactly as the internal route.",
        "operationId": "platformAppStoreCheckoutPlace",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "bistro"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "code": "EQ0MS2",
                      "kind": "store_order",
                      "store": {
                        "id": 31,
                        "slug": "bistro",
                        "name": "Bistro",
                        "logo_url": null
                      },
                      "order_type": "delivery",
                      "status": "pending_payment",
                      "status_label": "Pending payment",
                      "fulfillment_status": "new",
                      "fulfillment_label": "New",
                      "paid": false,
                      "total": 29.0,
                      "currency": "CAD",
                      "items_count": 2,
                      "table_code": null,
                      "created_at": "2026-10-14T12:00:00-04:00",
                      "channel": "app",
                      "requested_at": null,
                      "promised_at": "2026-10-14T12:35:00-04:00",
                      "paid_at": null,
                      "subtotal": 25.0,
                      "delivery_fee": 4.0,
                      "tax": 0.0,
                      "tip": 0.0,
                      "discount": 0.0,
                      "coupon_code": null,
                      "refunded_amount": 0.0,
                      "payment_method": "stripe",
                      "contact": {
                        "name": "Ada",
                        "telephone": "+15145550100",
                        "email": "ada@example.com"
                      },
                      "address": {
                        "address_1": "10 Rue Test",
                        "address_2": null,
                        "city": "Montreal",
                        "province": "QC",
                        "country": "CA",
                        "postcode": "H2X 2Z2",
                        "latitude": 45.51,
                        "longitude": -73.57
                      },
                      "delivery_instruction": null,
                      "note": null,
                      "items": [
                        {
                          "id": 1,
                          "product_id": 41,
                          "product_variant_id": null,
                          "name": "Burger",
                          "qty": 2,
                          "refunded_qty": 0,
                          "unit_price": 12.5,
                          "total": 25.0,
                          "options": [],
                          "review_rating": null
                        }
                      ],
                      "events": [
                        {
                          "track": "status",
                          "from": null,
                          "to": "pending_payment",
                          "at": "2026-10-14T12:00:00-04:00"
                        },
                        {
                          "track": "status",
                          "from": "pending_payment",
                          "to": "paid",
                          "at": "2026-10-14T12:01:10-04:00"
                        }
                      ],
                      "tracking_number": null,
                      "locker": null,
                      "actions": {
                        "can_pay": true,
                        "can_cancel": true,
                        "can_reorder": true,
                        "can_return": true,
                        "return_pending": false,
                        "can_review": true
                      },
                      "web_url": "https://shop.example.com/account/order/EQ0MS2"
                    },
                    "payment": {
                      "method": "stripe",
                      "client_secret": "pi_3Q_secret_abc",
                      "publishable_key": "pk_live_123",
                      "merchant_country": "CA",
                      "merchant_display_name": "Bistro",
                      "amount": 29.0,
                      "currency": "CAD"
                    },
                    "tab": null
                  }
                }
              }
            }
          },
          "422": {
            "description": "CHECKOUT_VALIDATION_FAILED (and the other 422 codes listed above)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "CHECKOUT_VALIDATION_FAILED",
                  "message": "Please check your order and address.",
                  "errors": [
                    "price_changed",
                    "out_of_delivery_area"
                  ],
                  "reasons": {
                    "price_changed": "Some prices have changed. Please review your cart.",
                    "out_of_delivery_area": "Sorry, this store does not deliver to your address."
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "order_type": {
                    "type": "string",
                    "enum": [
                      "delivery",
                      "collection",
                      "dine_in",
                      "locker"
                    ]
                  },
                  "name": {
                    "type": "string"
                  },
                  "telephone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "address_1": {
                    "type": "string"
                  },
                  "address_2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "province": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string"
                  },
                  "postcode": {
                    "type": "string"
                  },
                  "latitude": {
                    "type": "number"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "delivery_instruction": {
                    "type": "string"
                  },
                  "note": {
                    "type": "string"
                  },
                  "shelf_id": {
                    "type": "integer"
                  },
                  "table_code": {
                    "type": "string"
                  },
                  "requested_at": {
                    "type": "string"
                  },
                  "tip": {
                    "type": "number"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "payment_method": {
                    "type": "string",
                    "enum": [
                      "stripe",
                      "offline",
                      "wallet"
                    ]
                  }
                }
              },
              "example": {
                "order_type": "delivery",
                "name": "Ada",
                "telephone": "+15145550100",
                "email": "ada@example.com",
                "address_1": "10 Rue Test",
                "city": "Montreal",
                "postcode": "H2X 2Z2"
              }
            }
          }
        },
        "x-route-name": "openapp.store.checkout.place",
        "x-graphql": "platformAppStoreCheckoutPlace"
      }
    },
    "/app/v1/store-orders": {
      "get": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "The account's store orders at this client, newest first",
        "description": "The account's store orders at this client, newest first. Orders of the linked identity, and orders without identity under the account's e-mail or phone; group buy orders and smart-locker cabinet sales have their own lists. scope=open|past, page, per_page (max 50). include=locker (optional) adds the account's smart-locker cabinet purchases (the locker shop's own list, when the client's locker shop is on; no locker shop capability of the app is needed to list them) to the same list, newest first: every row then carries source, store (the store order row as without include; its channel stays the sales channel) or locker (the row of GET .../locker-shop/orders, opened by its id there); an order in both lists is a store order; each channel applies its own scope. Without include the answer is unchanged. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrders",
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "past"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50
            }
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "locker: also the smart-locker cabinet purchases, one list with a source on every row",
            "schema": {
              "type": "string",
              "enum": [
                "locker"
              ]
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "code": "EQ0MS2",
                        "kind": "store_order",
                        "store": {
                          "id": 31,
                          "slug": "bistro",
                          "name": "Bistro",
                          "logo_url": null
                        },
                        "order_type": "delivery",
                        "status": "paid",
                        "status_label": "Paid",
                        "fulfillment_status": "new",
                        "fulfillment_label": "New",
                        "paid": true,
                        "total": 29.0,
                        "currency": "CAD",
                        "items_count": 2,
                        "table_code": null,
                        "created_at": "2026-10-14T12:00:00-04:00"
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 20,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "APP_CONTEXT_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.store-orders.index",
        "x-graphql": "platformAppStoreOrders"
      }
    },
    "/app/v1/store-orders/{code}": {
      "get": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "One store order of the account",
        "description": "One store order of the account: status, lines, timeline, locker pickup and the actions open to the buyer. Errors: 404 ORDER_NOT_FOUND. items[].options is always a list of the option groups chosen for the line (empty without options): [{attachment_id: int|null, store_option_id: int|null, name: string, values: [{store_option_value_id: int|null, value: string, delta: number}]}] (delta = the price added per unit by that choice, already included in unit_price). locker (locker pickup orders, else null): {cabinet, address, pickup_code, pickup_due_at, remaining, items, door_open, can_open, refund_available}; locker.items is always a list of the order's cells: [{id: int, name: string, status: string (sold = waiting to be opened, opened = door open now, collected, expired, removed), compartment_number: string|null (the lock board's door number), pickup_number: int|null (the number shown on the door)}]. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrder",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [
                          {
                            "attachment_id": 12,
                            "store_option_id": 4,
                            "name": "Size",
                            "values": [
                              {
                                "store_option_value_id": 9,
                                "value": "Large",
                                "delta": 1.5
                              }
                            ]
                          }
                        ],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.store-orders.show",
        "x-graphql": "platformAppStoreOrder"
      }
    },
    "/app/v1/store-orders/{code}/pay": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Pay an unpaid order whose payment was left unfinished",
        "description": "Pay an unpaid order whose payment was left unfinished: the same payment object as place. Keeps the order's PaymentIntent while Stripe still accepts it (reused_intent true), otherwise starts a new one as checkout does; present the PaymentSheet, then call confirm-payment. Only while actions.can_pay is true. Errors: 404 ORDER_NOT_FOUND, 409 NOT_AWAITING_PAYMENT (paid, cancelled, refunded, a tab round or paid at the counter), 409 ORDER_ALREADY_PAID (the intent had already succeeded: the order is settled now, data carries it), 422 PAYMENT_ERROR. payment_method wallet pays the order from the account's balance instead, where the store takes it: the answer carries the paid order and payment.method wallet; a card payment that already succeeded wins (409 ORDER_ALREADY_PAID). Errors for wallet: 422 PAYMENT_METHOD_UNAVAILABLE, 422 INSUFFICIENT_BALANCE. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderPay",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "code": "EQ0MS2",
                      "kind": "store_order",
                      "store": {
                        "id": 31,
                        "slug": "bistro",
                        "name": "Bistro",
                        "logo_url": null
                      },
                      "order_type": "delivery",
                      "status": "pending_payment",
                      "status_label": "Pending payment",
                      "fulfillment_status": "new",
                      "fulfillment_label": "New",
                      "paid": false,
                      "total": 29.0,
                      "currency": "CAD",
                      "items_count": 2,
                      "table_code": null,
                      "created_at": "2026-10-14T12:00:00-04:00",
                      "channel": "app",
                      "requested_at": null,
                      "promised_at": "2026-10-14T12:35:00-04:00",
                      "paid_at": null,
                      "subtotal": 25.0,
                      "delivery_fee": 4.0,
                      "tax": 0.0,
                      "tip": 0.0,
                      "discount": 0.0,
                      "coupon_code": null,
                      "refunded_amount": 0.0,
                      "payment_method": "stripe",
                      "contact": {
                        "name": "Ada",
                        "telephone": "+15145550100",
                        "email": "ada@example.com"
                      },
                      "address": {
                        "address_1": "10 Rue Test",
                        "address_2": null,
                        "city": "Montreal",
                        "province": "QC",
                        "country": "CA",
                        "postcode": "H2X 2Z2",
                        "latitude": 45.51,
                        "longitude": -73.57
                      },
                      "delivery_instruction": null,
                      "note": null,
                      "items": [
                        {
                          "id": 1,
                          "product_id": 41,
                          "product_variant_id": null,
                          "name": "Burger",
                          "qty": 2,
                          "refunded_qty": 0,
                          "unit_price": 12.5,
                          "total": 25.0,
                          "options": [],
                          "review_rating": null
                        }
                      ],
                      "events": [
                        {
                          "track": "status",
                          "from": null,
                          "to": "pending_payment",
                          "at": "2026-10-14T12:00:00-04:00"
                        },
                        {
                          "track": "status",
                          "from": "pending_payment",
                          "to": "paid",
                          "at": "2026-10-14T12:01:10-04:00"
                        }
                      ],
                      "tracking_number": null,
                      "locker": null,
                      "actions": {
                        "can_pay": true,
                        "can_cancel": true,
                        "can_reorder": true,
                        "can_return": true,
                        "return_pending": false,
                        "can_review": true
                      },
                      "web_url": "https://shop.example.com/account/order/EQ0MS2"
                    },
                    "payment": {
                      "method": "stripe",
                      "client_secret": "pi_3Q_secret_abc",
                      "publishable_key": "pk_live_123",
                      "merchant_country": "CA",
                      "merchant_display_name": "Bistro",
                      "amount": 29.0,
                      "currency": "CAD"
                    },
                    "reused_intent": true
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_method": {
                    "type": "string",
                    "enum": [
                      "stripe",
                      "wallet"
                    ],
                    "description": "wallet pays from the account balance; omitted or stripe resumes the card payment."
                  }
                }
              },
              "example": {
                "payment_method": "wallet"
              }
            }
          }
        },
        "x-route-name": "openapp.store-orders.pay",
        "x-graphql": "platformAppStoreOrderPay"
      }
    },
    "/app/v1/store-orders/{code}/confirm-payment": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "After the PaymentSheet",
        "description": "After the PaymentSheet: ask Stripe about the order's PaymentIntent and settle the order once. Errors: 404 ORDER_NOT_FOUND. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderConfirmPayment",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "paid": true,
                    "order": {
                      "code": "EQ0MS2",
                      "kind": "store_order",
                      "store": {
                        "id": 31,
                        "slug": "bistro",
                        "name": "Bistro",
                        "logo_url": null
                      },
                      "order_type": "delivery",
                      "status": "paid",
                      "status_label": "Paid",
                      "fulfillment_status": "new",
                      "fulfillment_label": "New",
                      "paid": true,
                      "total": 29.0,
                      "currency": "CAD",
                      "items_count": 2,
                      "table_code": null,
                      "created_at": "2026-10-14T12:00:00-04:00",
                      "channel": "app",
                      "requested_at": null,
                      "promised_at": "2026-10-14T12:35:00-04:00",
                      "paid_at": "2026-10-14T12:01:10-04:00",
                      "subtotal": 25.0,
                      "delivery_fee": 4.0,
                      "tax": 0.0,
                      "tip": 0.0,
                      "discount": 0.0,
                      "coupon_code": null,
                      "refunded_amount": 0.0,
                      "payment_method": "stripe",
                      "contact": {
                        "name": "Ada",
                        "telephone": "+15145550100",
                        "email": "ada@example.com"
                      },
                      "address": {
                        "address_1": "10 Rue Test",
                        "address_2": null,
                        "city": "Montreal",
                        "province": "QC",
                        "country": "CA",
                        "postcode": "H2X 2Z2",
                        "latitude": 45.51,
                        "longitude": -73.57
                      },
                      "delivery_instruction": null,
                      "note": null,
                      "items": [
                        {
                          "id": 1,
                          "product_id": 41,
                          "product_variant_id": null,
                          "name": "Burger",
                          "qty": 2,
                          "refunded_qty": 0,
                          "unit_price": 12.5,
                          "total": 25.0,
                          "options": [],
                          "review_rating": null
                        }
                      ],
                      "events": [
                        {
                          "track": "status",
                          "from": null,
                          "to": "pending_payment",
                          "at": "2026-10-14T12:00:00-04:00"
                        },
                        {
                          "track": "status",
                          "from": "pending_payment",
                          "to": "paid",
                          "at": "2026-10-14T12:01:10-04:00"
                        }
                      ],
                      "tracking_number": null,
                      "locker": null,
                      "actions": {
                        "can_pay": false,
                        "can_cancel": true,
                        "can_reorder": true,
                        "can_return": true,
                        "return_pending": false,
                        "can_review": true
                      },
                      "web_url": "https://shop.example.com/account/order/EQ0MS2"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.store-orders.confirm-payment",
        "x-graphql": "platformAppStoreOrderConfirmPayment"
      }
    },
    "/app/v1/store-orders/{code}/cancel": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Cancel the order before the store accepts it",
        "description": "Cancel the order before the store accepts it; a paid order is refunded in full. Errors: 404 ORDER_NOT_FOUND. 409 CANCEL_NOT_ALLOWED, 422 CANCEL_FAILED. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderCancel",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Your order has been cancelled and refunded.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "refunded",
                    "status_label": "Refunded",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.store-orders.cancel",
        "x-graphql": "platformAppStoreOrderCancel"
      }
    },
    "/app/v1/store-orders/{code}/locker-open": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Open the next door of a paid locker pickup, on the buyer's own press at the cabi",
        "description": "Open the next door of a paid locker pickup, on the buyer's own press at the cabinet. Errors: 404 ORDER_NOT_FOUND. 409 NOT_A_LOCKER_ORDER, 404 CABINET_NOT_FOUND, 422/409 with code of the refusal (door not opened). Needs the locker.remote_open capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderLockerOpen",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Door 3 opened: Cola",
                  "door_opened": true,
                  "refund_available": false,
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.remote_open"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.store-orders.locker-open",
        "x-graphql": "platformAppStoreOrderLockerOpen",
        "x-capability": "locker.remote_open"
      }
    },
    "/app/v1/store-orders/{code}/locker-refund": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Refund a locker pickup whose door never opened",
        "description": "Refund a locker pickup whose door never opened. Errors: 404 ORDER_NOT_FOUND. 409 NOT_A_LOCKER_ORDER, 404 CABINET_NOT_FOUND, 409 REFUND_REFUSED. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderLockerRefund",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Refund issued.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.store-orders.locker-refund",
        "x-graphql": "platformAppStoreOrderLockerRefund"
      }
    },
    "/app/v1/store-orders/{code}/reorder": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Put the order's lines back into the buyer's cart at the store",
        "description": "Put the order's lines back into the buyer's cart at the store. Errors: 404 ORDER_NOT_FOUND. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderReorder",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "The items were added to your cart.",
                  "data": {
                    "added": 1,
                    "skipped": 0,
                    "store_slug": "bistro"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.store-orders.reorder",
        "x-graphql": "platformAppStoreOrderReorder"
      }
    },
    "/app/v1/store-orders/{code}/return": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Ask the store to take a paid or completed order back",
        "description": "Ask the store to take a paid or completed order back. Errors: 404 ORDER_NOT_FOUND. 409 RETURN_NOT_ALLOWED, 409 RETURN_ALREADY_OPEN, 422 VALIDATION_FAILED. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderReturn",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Return requested.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              },
              "example": {
                "reason": "Cold on arrival"
              }
            }
          }
        },
        "x-route-name": "openapp.store-orders.return",
        "x-graphql": "platformAppStoreOrderReturn"
      }
    },
    "/app/v1/store-orders/{code}/review/{productId}": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Rate one product of the order (1 to 5, optional comment)",
        "description": "Rate one product of the order (1 to 5, optional comment); a second rating replaces the first. Errors: 404 ORDER_NOT_FOUND. 404 PRODUCT_NOT_IN_ORDER, 422 VALIDATION_FAILED. Answered exactly as the internal route.",
        "operationId": "platformAppStoreOrderReview",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 41
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Thanks for your review.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rating": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "comment": {
                    "type": "string",
                    "maxLength": 2000
                  }
                }
              },
              "example": {
                "rating": 5,
                "comment": "Good"
              }
            }
          }
        },
        "x-route-name": "openapp.store-orders.review",
        "x-graphql": "platformAppStoreOrderReview"
      }
    },
    "/app/v1/locker-locations/{locationId}/shop": {
      "get": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "What a location's cabinets have for sale",
        "description": "Every cabinet at the location with the shop switched on, its stores, and per product the count of units in cells, the unit price and the temperature class. Nothing is held by reading. Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopCatalog",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "fr"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The catalogue",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "location": {
                      "id": 700,
                      "name": "Central Station"
                    },
                    "max_items_per_sale": 5,
                    "cabinets": [
                      {
                        "shelf_id": 312,
                        "shelf_code": "CAB-A",
                        "stores": [
                          {
                            "store": {
                              "id": 31,
                              "name": "Corner Shop",
                              "slug": "corner-shop",
                              "currency": "CAD"
                            },
                            "lines": [
                              {
                                "product_id": 81,
                                "product_variant_id": null,
                                "name": "Cola",
                                "variant_label": "",
                                "display_name": "Cola",
                                "sku": "COLA-1",
                                "barcode": null,
                                "unit_price": 3.5,
                                "image_url": null,
                                "storage_temperature": "chilled",
                                "storage_temperature_label": "Chilled",
                                "count": 3
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.catalog",
        "x-graphql": "platformAppLockerShopCatalog",
        "x-capability": "locker.shop"
      }
    },
    "/app/v1/locker-shop/items": {
      "get": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "Items in cells (merchant staff)",
        "description": "What the stores this account runs have in cabinet cells: every occupying item by default, or one status with `status`. Filter by cabinet or store. Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopItems",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "shelf_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "store_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "stocked",
                "held",
                "sold",
                "opened",
                "collected",
                "expired",
                "removed"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The items",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": 5001,
                        "store": {
                          "id": 31,
                          "name": "Corner Shop"
                        },
                        "cabinet": {
                          "id": 312,
                          "code": "CAB-A"
                        },
                        "compartment_number": "3",
                        "name": "Cola",
                        "sku": "COLA-1",
                        "status": "stocked",
                        "status_label": "For sale",
                        "expires_at": "2026-10-15T23:59:59-04:00",
                        "sales_order_id": null,
                        "pickup_due_at": null
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 50,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.items",
        "x-graphql": "platformAppLockerShopItems",
        "x-capability": "locker.shop"
      }
    },
    "/app/v1/locker-shop/orders": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "Buy from a cabinet",
        "description": "Holds the chosen units in that cabinet for the operator's hold time and raises the sale under the account's contact. Nothing is collected: pay it with POST …/pay/requests/{public_token}/pay using `data.payment`. At most the operator's items-per-sale from ONE store. Held units go back on sale if the hold runs out unpaid. Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopCreateOrder",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "shelf_id",
                  "store_id",
                  "lines"
                ],
                "properties": {
                  "shelf_id": {
                    "type": "integer"
                  },
                  "store_id": {
                    "type": "integer"
                  },
                  "lines": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "product_id",
                        "qty"
                      ],
                      "properties": {
                        "product_id": {
                          "type": "integer"
                        },
                        "product_variant_id": {
                          "type": "integer",
                          "nullable": true
                        },
                        "qty": {
                          "type": "integer",
                          "minimum": 1
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "shelf_id": 312,
                "store_id": 31,
                "lines": [
                  {
                    "product_id": 81,
                    "qty": 2
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The sale, unpaid, with the payment request to settle it",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 9130,
                    "status": "pending_payment",
                    "paid": false,
                    "created_at": "2026-09-27T14:02:11-04:00",
                    "paid_at": null,
                    "total": 7.7,
                    "currency": "CAD",
                    "store": {
                      "id": 31,
                      "name": "Corner Shop"
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A",
                      "location_id": 700
                    },
                    "items_total": 2,
                    "remaining": 2,
                    "pickup_due_at": "2026-09-28 14:03:40",
                    "can_open": false,
                    "pickup_code": null,
                    "items": [
                      {
                        "id": 5001,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "3",
                        "pickup_number": 3
                      },
                      {
                        "id": 5002,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "4",
                        "pickup_number": 4
                      }
                    ],
                    "payment": {
                      "subject_type": "locker_shop",
                      "subject_id": 9130,
                      "public_token": "0f7c2b4e9a1d4f0b8c6e3a5d7b9f1c2e",
                      "amount": 7.7,
                      "currency": "CAD",
                      "expires_at": "2026-09-27T14:32:11-04:00",
                      "payable_in_app": true,
                      "pay_url": "https://app.example.com/pay/r/0f7c2b4e9a1d4f0b8c6e3a5d7b9f1c2e"
                    },
                    "refund_available": false
                  }
                }
              }
            }
          },
          "422": {
            "description": "Refused: not enough units, too many items, or the store does not sell here",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "SALE_REFUSED",
                  "message": "Not enough units of Cola in this cabinet."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.orders.create",
        "x-graphql": "platformAppLockerShopCreateOrder",
        "x-capability": "locker.shop"
      },
      "get": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "The caller's shop purchases",
        "description": "Newest first. `scope=open` keeps the ones still unpaid or awaiting pickup; `scope=past` the rest. A purchase is the caller's when it was raised under the account's own contact, which is what the payment layer matches on too. Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopOrders",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "past"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The purchases",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": 9130,
                        "status": "paid",
                        "paid": true,
                        "created_at": "2026-09-27T14:02:11-04:00",
                        "paid_at": "2026-09-27T14:03:40-04:00",
                        "total": 7.7,
                        "currency": "CAD",
                        "store": {
                          "id": 31,
                          "name": "Corner Shop"
                        },
                        "cabinet": {
                          "id": 312,
                          "code": "CAB-A",
                          "location_id": 700
                        },
                        "items_total": 2,
                        "remaining": 2,
                        "pickup_due_at": "2026-09-28 14:03:40",
                        "can_open": true
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 20,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.orders.index",
        "x-graphql": "platformAppLockerShopOrders",
        "x-capability": "locker.shop"
      }
    },
    "/app/v1/locker-shop/orders/{id}": {
      "get": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "One shop purchase",
        "description": "Its items with their doors, the pickup code once paid, how many doors are left, whether a door may be opened now, and while unpaid the payment request. `refund_available` is true only for a paid purchase none of whose doors was ever opened (D12). Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopOrder",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The purchase",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 9130,
                    "status": "paid",
                    "paid": true,
                    "created_at": "2026-09-27T14:02:11-04:00",
                    "paid_at": "2026-09-27T14:03:40-04:00",
                    "total": 7.7,
                    "currency": "CAD",
                    "store": {
                      "id": 31,
                      "name": "Corner Shop"
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A",
                      "location_id": 700
                    },
                    "items_total": 2,
                    "remaining": 2,
                    "pickup_due_at": "2026-09-28 14:03:40",
                    "can_open": true,
                    "pickup_code": "K7Q2M9",
                    "items": [
                      {
                        "id": 5001,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "3",
                        "pickup_number": 3
                      },
                      {
                        "id": 5002,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "4",
                        "pickup_number": 4
                      }
                    ],
                    "payment": null,
                    "refund_available": true
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not the caller's, or unknown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "SALE_NOT_FOUND",
                  "message": "This sale was not found."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.orders.show",
        "x-graphql": "platformAppLockerShopOrder",
        "x-capability": "locker.shop"
      }
    },
    "/app/v1/locker-shop/orders/{id}/open": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "Open the next door",
        "description": "Opens the next unopened cell of a paid purchase — one door per call, the next only once the cabinet has seen the previous one closed. This is the buyer's own press: the app must tell them to stand at the cabinet first, because the server cannot know. Never happens on the payment. On failure `refund_available` says whether the D12 refund may be asked for. Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopOpen",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The door opened",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Pickup successful",
                  "door_opened": true,
                  "refund_available": false,
                  "data": {
                    "id": 9130,
                    "status": "paid",
                    "paid": true,
                    "created_at": "2026-09-27T14:02:11-04:00",
                    "paid_at": "2026-09-27T14:03:40-04:00",
                    "total": 7.7,
                    "currency": "CAD",
                    "store": {
                      "id": 31,
                      "name": "Corner Shop"
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A",
                      "location_id": 700
                    },
                    "items_total": 2,
                    "remaining": 1,
                    "pickup_due_at": "2026-09-28 14:03:40",
                    "can_open": false,
                    "pickup_code": "K7Q2M9",
                    "items": [
                      {
                        "id": 5001,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "3",
                        "pickup_number": 3
                      },
                      {
                        "id": 5002,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "4",
                        "pickup_number": 4
                      }
                    ],
                    "payment": null,
                    "refund_available": true
                  }
                }
              }
            }
          },
          "422": {
            "description": "The door did not open, or one is still open",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "DOOR_OPEN",
                  "message": "Close the open door before opening the next one.",
                  "door_opened": false,
                  "refund_available": false,
                  "data": {
                    "id": 9130,
                    "status": "paid",
                    "paid": true,
                    "created_at": "2026-09-27T14:02:11-04:00",
                    "paid_at": "2026-09-27T14:03:40-04:00",
                    "total": 7.7,
                    "currency": "CAD",
                    "store": {
                      "id": 31,
                      "name": "Corner Shop"
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A",
                      "location_id": 700
                    },
                    "items_total": 2,
                    "remaining": 2,
                    "pickup_due_at": "2026-09-28 14:03:40",
                    "can_open": true,
                    "pickup_code": "K7Q2M9",
                    "items": [
                      {
                        "id": 5001,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "3",
                        "pickup_number": 3
                      },
                      {
                        "id": 5002,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "4",
                        "pickup_number": 4
                      }
                    ],
                    "payment": null,
                    "refund_available": true
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.orders.open",
        "x-graphql": "platformAppLockerShopOpen",
        "x-capability": "locker.shop"
      }
    },
    "/app/v1/locker-shop/access-codes": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "Issue a staff code (merchant staff)",
        "description": "For the owner of a store, or a sub-account with access to it: a code that opens the merchant menu on one cabinet the store is bound to, valid for the operator's configured hours. Shown once. Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopIssueAccessCode",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "store_id",
                  "shelf_id"
                ],
                "properties": {
                  "store_id": {
                    "type": "integer"
                  },
                  "shelf_id": {
                    "type": "integer"
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 191
                  }
                }
              },
              "example": {
                "store_id": 31,
                "shelf_id": 312,
                "label": "Morning restock"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 77,
                    "code": "H4M2Q9",
                    "store": {
                      "id": 31,
                      "name": "Corner Shop"
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A"
                    },
                    "expires_at": "2026-09-27T18:02:11-04:00"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.access-codes",
        "x-graphql": "platformAppLockerShopIssueAccessCode",
        "x-capability": "locker.shop"
      }
    },
    "/app/v1/locker-shop/orders/{id}/refund-request": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Shop"
        ],
        "summary": "Ask for a refund after a door would not open",
        "description": "The one automatic refund (D12): granted only when the purchase is paid and none of its cells was ever opened since payment. The money goes back the way it came and the goods go back on sale. Anything else is the merchant's decision. Requires the locker.shop capability (403 APP_CAPABILITY_DISABLED otherwise) and the operator's shop switch. Needs the locker.shop capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppLockerShopRefundRequest",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Refunded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 9130,
                    "status": "refunded",
                    "paid": true,
                    "created_at": "2026-09-27T14:02:11-04:00",
                    "paid_at": "2026-09-27T14:03:40-04:00",
                    "total": 7.7,
                    "currency": "CAD",
                    "store": {
                      "id": 31,
                      "name": "Corner Shop"
                    },
                    "cabinet": {
                      "id": 312,
                      "code": "CAB-A",
                      "location_id": 700
                    },
                    "items_total": 2,
                    "remaining": 0,
                    "pickup_due_at": "2026-09-28 14:03:40",
                    "can_open": false,
                    "pickup_code": "K7Q2M9",
                    "items": [
                      {
                        "id": 5001,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "3",
                        "pickup_number": 3
                      },
                      {
                        "id": 5002,
                        "name": "Cola",
                        "status": "sold",
                        "compartment_number": "4",
                        "pickup_number": 4
                      }
                    ],
                    "payment": null,
                    "refund_available": false,
                    "message": "The payment was refunded and the goods are back on sale."
                  }
                }
              }
            }
          },
          "409": {
            "description": "Not eligible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "REFUND_REFUSED",
                  "message": "A refund is not possible: a door of this sale was already opened."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.shop"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-shop.orders.refund",
        "x-graphql": "platformAppLockerShopRefundRequest",
        "x-capability": "locker.shop"
      }
    },
    "/app/v1/locker-resale/terms": {
      "get": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Handover terms for the buyer",
        "description": "The terms a buyer ticks when opening a handover, in their language. Read it before opening a deal and show it: the deal snapshots the operator's current version as the one its buyer accepted, so an app that never showed it has agreed on their behalf. The operator's own wording replaces ours whole where they have written it; a language left blank falls back to ours. Send the version back when opening the deal — each deal records the wording its buyer actually accepted, so a later edit never rewrites what somebody agreed to. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "lockerResaleTerms",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The terms and the version to record",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "version": "platform-v1",
                  "source": "platform",
                  "text": [
                    "We pass the goods on; we are not the seller.",
                    "The money for the goods is between the two of you."
                  ]
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.terms",
        "x-graphql": "lockerResaleTerms"
      }
    },
    "/app/v1/locker-resale/deals": {
      "get": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Handovers this customer is a party to",
        "description": "Every handover where this customer is the buyer or the seller, newest first. Scoped to the person, not to the business: one customer never reads another's handovers. What each entry carries depends on which party the reader is — only the seller sees the drop-off code, the amount owed and the three decisions that are his; the buyer sees the pickup code and the cabinet address, and only once the seller has released it. When one account is both the buyer and the seller of a deal — the seller needs no account, so a seller contact that matches the caller's own is linked to it — the deal is answered as the seller, which is the larger of the two views, with also_buyer true and the buyer's pickup_code included. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "lockerResaleDeals",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "open",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Handovers, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "deals": [
                    {
                      "id": 4108,
                      "deal_no": "RH2609170001",
                      "status": "awaiting_release",
                      "status_label": "Waiting for the pickup code",
                      "role": "seller",
                      "item_title": "Road bike",
                      "item_price": 420.0,
                      "item_currency": "CAD",
                      "created_at": "2026-09-17 10:12:04",
                      "dropoff_deadline": "2026-09-20 10:12:04",
                      "release_due_at": "2026-09-18 11:40:00",
                      "expires_at": "2026-09-21 11:40:00",
                      "dropoff_code": null,
                      "return_code": null,
                      "outstanding_amount": 0.0,
                      "payment": null,
                      "can_release": true,
                      "can_revoke": false,
                      "can_abort": true,
                      "can_cancel": false,
                      "location": "Cabinet A — Plaza Sud",
                      "compartment_number": "12"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "per_page": 25,
                    "total": 1
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.index",
        "x-graphql": "lockerResaleDeals"
      },
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Open a handover",
        "description": "The caller is the seller: their own name, phone, e-mail and language come from the account. The buyer needs no account — a phone number or an e-mail address is enough, and one of the two is required; the pickup code is sent there once the seller releases it. The answer carries the seller's drop-off code, which is also sent to the seller by SMS or e-mail; no cabinet is chosen here, because any of the operator's cabinets that take handovers may be used. Opening a deal as the buyer is no longer supported: a request that still carries seller_name, seller_phone or seller_email is refused with 422. The agreed price is recorded for the two parties only — the platform never collects the money for the goods. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "createLockerResaleDeal",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "buyer_name": {
                    "type": "string",
                    "description": "The buyer's name"
                  },
                  "buyer_phone": {
                    "type": "string",
                    "description": "Required unless buyer_email is given"
                  },
                  "buyer_email": {
                    "type": "string",
                    "description": "Required unless buyer_phone is given"
                  },
                  "buyer_locale": {
                    "type": "string",
                    "description": "Language the buyer is written to in; defaults to the buyer's account language when the contact matches one, otherwise the request language"
                  },
                  "item_title": {
                    "type": "string"
                  },
                  "item_description": {
                    "type": "string"
                  },
                  "item_price": {
                    "type": "number"
                  },
                  "item_currency": {
                    "type": "string"
                  }
                },
                "additionalProperties": true
              },
              "example": {
                "buyer_name": "Alex Tremblay",
                "buyer_phone": "+15145550188",
                "item_title": "Road bike",
                "item_description": "54cm frame, blue",
                "item_price": 420.0,
                "item_currency": "CAD"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The handover, with the seller's drop-off code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "deal": {
                    "id": 5120,
                    "deal_no": "RS260917A1B2C3",
                    "status": "awaiting_dropoff",
                    "status_label": "Awaiting drop-off",
                    "role": "seller",
                    "item_title": "Road bike",
                    "item_price": 420.0,
                    "item_currency": "CAD",
                    "created_at": "2026-09-17 10:02:11",
                    "dropoff_deadline": "2026-09-20 10:02:11",
                    "release_due_at": null,
                    "expires_at": null,
                    "can_cancel": true,
                    "dropoff_code": "483920",
                    "return_code": null,
                    "outstanding_amount": "0.00",
                    "payment": null,
                    "can_release": false,
                    "can_revoke": false,
                    "can_abort": false,
                    "location": null,
                    "compartment_number": null,
                    "address": null
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "422": {
            "description": "The buyer has no contact, the seller's account has neither phone nor e-mail, a seller_* field was sent (opening as the buyer is no longer supported), or one party already has as many open handovers as the operator allows"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.store",
        "x-graphql": "createLockerResaleDeal"
      }
    },
    "/app/v1/locker-resale/deals/{id}": {
      "get": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "One handover",
        "description": "One handover as the calling party may see it, with the timeline of what both parties did — never the other party's phone number, IP or device. A seller who owes money also gets the `payment` block: the subject the scan-to-pay endpoints take, which is what lets him pay with anything the operator accepts rather than only a balance or a saved card. When one account is both the buyer and the seller of a deal — the seller needs no account, so a seller contact that matches the caller's own is linked to it — the deal is answered as the seller, which is the larger of the two views, with also_buyer true and the buyer's pickup_code included. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "lockerResaleDeal",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The handover and its timeline",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "deal": {
                    "id": 4108,
                    "deal_no": "RH2609170001",
                    "status": "awaiting_payment",
                    "status_label": "Waiting for payment",
                    "role": "seller",
                    "item_title": "Road bike",
                    "item_price": 420.0,
                    "item_currency": "CAD",
                    "created_at": "2026-09-17 10:12:04",
                    "dropoff_deadline": "2026-09-20 10:12:04",
                    "release_due_at": "2026-09-18 11:40:00",
                    "expires_at": "2026-09-21 11:40:00",
                    "dropoff_code": null,
                    "return_code": null,
                    "outstanding_amount": 6.0,
                    "payment": {
                      "amount": 6.0,
                      "currency": "CAD",
                      "subject_type": "locker_resale",
                      "subject_id": 4108,
                      "payable_in_app": true,
                      "public_token": "0f7c2b4e9a1d4f0b8c6e3a5d7b9f1c2e",
                      "pay_url": "https://app.example.com/pay/r/0f7c2b4e9a1d4f0b8c6e3a5d7b9f1c2e"
                    },
                    "can_release": false,
                    "can_revoke": false,
                    "can_abort": true,
                    "can_cancel": false,
                    "location": "Cabinet A — Plaza Sud",
                    "compartment_number": "12"
                  },
                  "timeline": [
                    {
                      "type": "created",
                      "label": "Deal opened",
                      "role": "buyer",
                      "occurred_at": "2026-09-17 10:12:04"
                    },
                    {
                      "type": "dropoff_closed",
                      "label": "Goods placed",
                      "role": "seller",
                      "occurred_at": "2026-09-17 11:38:52"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "404": {
            "description": "No handover with that id that this customer is a party to"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.show",
        "x-graphql": "lockerResaleDeal"
      }
    },
    "/app/v1/locker-resale/deals/{id}/release": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Send the buyer the pickup code",
        "description": "The seller's decision, and the only thing that gives the buyer a code — nothing releases it automatically. Until it is pressed the buyer knows a cabinet holds the goods but not which one. Refused before the goods are in, before the fee is settled, and after the deal has ended. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "releaseLockerResaleCode",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Released; the buyer has been told",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "deal": {
                    "id": 4108,
                    "deal_no": "RH2609170001",
                    "status": "active",
                    "status_label": "Waiting for the buyer",
                    "role": "seller",
                    "item_title": "Road bike",
                    "item_price": 420.0,
                    "item_currency": "CAD",
                    "created_at": "2026-09-17 10:12:04",
                    "dropoff_deadline": "2026-09-20 10:12:04",
                    "release_due_at": "2026-09-18 11:40:00",
                    "expires_at": "2026-09-21 11:40:00",
                    "dropoff_code": null,
                    "return_code": null,
                    "outstanding_amount": 0.0,
                    "payment": null,
                    "can_release": false,
                    "can_revoke": true,
                    "can_abort": true,
                    "can_cancel": false,
                    "location": "Cabinet A — Plaza Sud",
                    "compartment_number": "12"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "404": {
            "description": "No handover with that id that this customer is a party to"
          },
          "422": {
            "description": "Not the seller, or the deal is not waiting to be released"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.release",
        "x-graphql": "releaseLockerResaleCode"
      }
    },
    "/app/v1/locker-resale/deals/{id}/revoke-code": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Revoke the pickup code",
        "description": "Kills the code the buyer holds and puts the deal back to waiting; the buyer is told at once. Refused once a door has been opened for the buyer — an open door cannot be taken back by voiding a code. The send-by deadline is NOT extended: revoking after it has passed hands the deal back to the seller at the next sweep, which the app must say before the button is pressed. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "revokeLockerResaleCode",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked; the buyer has been told",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "deal": {
                    "id": 4108,
                    "deal_no": "RH2609170001",
                    "status": "awaiting_release",
                    "status_label": "Waiting for the pickup code",
                    "role": "seller",
                    "item_title": "Road bike",
                    "item_price": 420.0,
                    "item_currency": "CAD",
                    "created_at": "2026-09-17 10:12:04",
                    "dropoff_deadline": "2026-09-20 10:12:04",
                    "release_due_at": "2026-09-18 11:40:00",
                    "expires_at": "2026-09-21 11:40:00",
                    "dropoff_code": null,
                    "return_code": null,
                    "outstanding_amount": 0.0,
                    "payment": null,
                    "can_release": true,
                    "can_revoke": false,
                    "can_abort": true,
                    "can_cancel": false,
                    "location": "Cabinet A — Plaza Sud",
                    "compartment_number": "12"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "404": {
            "description": "No handover with that id that this customer is a party to"
          },
          "422": {
            "description": "Not the seller, no code out, or a door is already opening for the buyer"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.revoke",
        "x-graphql": "revokeLockerResaleCode"
      }
    },
    "/app/v1/locker-resale/deals/{id}/abort": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Call the handover off",
        "description": "The seller ends the deal and takes his goods back: the buyer's code stops working, a return code is sent to the seller, and the cabinet fee is not refunded. Available while the goods are in a cabinet and before the buyer has collected them. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "abortLockerResaleDeal",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "reason": "Buyer never paid me"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Called off; the return code is on its way",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "deal": {
                    "id": 4108,
                    "deal_no": "RH2609170001",
                    "status": "aborted",
                    "status_label": "Called off",
                    "role": "seller",
                    "item_title": "Road bike",
                    "item_price": 420.0,
                    "item_currency": "CAD",
                    "created_at": "2026-09-17 10:12:04",
                    "dropoff_deadline": "2026-09-20 10:12:04",
                    "release_due_at": "2026-09-18 11:40:00",
                    "expires_at": "2026-09-21 11:40:00",
                    "dropoff_code": null,
                    "return_code": "284193",
                    "outstanding_amount": 0.0,
                    "payment": null,
                    "can_release": false,
                    "can_revoke": false,
                    "can_abort": false,
                    "can_cancel": false,
                    "location": "Cabinet A — Plaza Sud",
                    "compartment_number": "12"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "404": {
            "description": "No handover with that id that this customer is a party to"
          },
          "422": {
            "description": "Not the seller, or the deal has already ended"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.abort",
        "x-graphql": "abortLockerResaleDeal"
      }
    },
    "/app/v1/locker-resale/deals/{id}/cancel": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Cancel before anything is dropped off",
        "description": "Either party may walk away while no goods have been placed: nothing has been paid, no compartment is held, and the drop-off code stops working. Once the goods are in a cabinet this is refused — from then on the seller calls the deal off instead, and the buyer waits. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "cancelLockerResaleDeal",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "deal": {
                    "id": 4108,
                    "deal_no": "RH2609170001",
                    "status": "cancelled",
                    "status_label": "Cancelled",
                    "role": "seller",
                    "item_title": "Road bike",
                    "item_price": 420.0,
                    "item_currency": "CAD",
                    "created_at": "2026-09-17 10:12:04",
                    "dropoff_deadline": "2026-09-20 10:12:04",
                    "release_due_at": "2026-09-18 11:40:00",
                    "expires_at": "2026-09-21 11:40:00",
                    "dropoff_code": null,
                    "return_code": null,
                    "outstanding_amount": 0.0,
                    "payment": null,
                    "can_release": false,
                    "can_revoke": false,
                    "can_abort": false,
                    "can_cancel": false,
                    "location": "Cabinet A — Plaza Sud",
                    "compartment_number": "12"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "404": {
            "description": "No handover with that id that this customer is a party to"
          },
          "422": {
            "description": "The goods are already in a cabinet"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.cancel",
        "x-graphql": "cancelLockerResaleDeal"
      }
    },
    "/app/v1/locker-resale/deals/{id}/report": {
      "post": {
        "tags": [
          "Platform Apps",
          "Locker Resale"
        ],
        "summary": "Report a problem after collecting",
        "description": "The buyer says what was in the box. It is a record for the operator to read beside the cabinet's own evidence, not a case: the platform never held the money for the goods, so it does not arbitrate, refund, or suspend anybody on the strength of it. Open for seven days after collection — after that the compartment has been reused and the record is no longer about this handover. Photos may be uploaded as files or sent as base64. The reason is one of empty, damaged, not_as_described or other. Needs the locker.resale capability on the token (granted to the developer as app.locker_resale); answered exactly as the internal route.",
        "operationId": "reportLockerResaleDeal",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "reason": "not_as_described",
                "description": "The frame is cracked.",
                "photos": [
                  "<base64>"
                ]
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "photos[]": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "report": {
                    "id": 91,
                    "reason": "not_as_described",
                    "status": "open",
                    "created_at": "2026-09-19 09:02:11"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.resale; or the handover capability is off for this client, or the module is off for the business"
          },
          "404": {
            "description": "No handover with that id that this customer is a party to"
          },
          "422": {
            "description": "Not the buyer, the goods were never collected, or the seven days have passed"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.locker-resale.report",
        "x-graphql": "reportLockerResaleDeal"
      }
    },
    "/app/v1/group-buys/{code}": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get a group buy campaign",
        "description": "Signed-in customer of the customer app or MiBox. The campaign a buyer opens: campaign (title, cutoff_at and expected_delivery_at on the store's clock, orderable, home_fee {mode fixed | store_areas | free, fee, free_over}, store, web_url), items [{id, name, group_price, regular_price}], pickup choices [{key point:{id} | leader:{group id}, name, address, notes, leader}], home (home delivery offered), leader (the leader of a marked link, D24: that leader's point comes first), address_suggestions, currency, tax_rate. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuy",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "leader",
            "in": "query",
            "required": false,
            "description": "The leader mark of a shared link (?leader=).",
            "schema": {
              "type": "string",
              "example": "ANNPORCH01"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a group buy campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "campaign",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "items": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "regular_price": 6
                      }
                    ],
                    "pickup": [
                      {
                        "key": "leader:1",
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      {
                        "key": "point:1",
                        "name": "Library",
                        "address": "12 King St, Toronto, M5H 2N2",
                        "notes": "Sat 10-12",
                        "leader": false
                      }
                    ],
                    "home": true,
                    "leader": {
                      "mark": "ANNPORCH01",
                      "name": "Ann's porch"
                    },
                    "address_suggestions": false,
                    "currency": "CAD",
                    "tax_rate": 13,
                    "guest_verification_channel": null
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.show",
        "x-graphql": "platformAppGroupBuy",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buys/{code}/address/details": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get a suggested address",
        "description": "Signed-in customer of the customer app or MiBox. The fields of a chosen suggestion (address null when it cannot be read). 404 GROUP_BUY_NO_HOME_DELIVERY when the campaign has no home delivery. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyAddressDetails",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "place_id",
            "in": "query",
            "required": true,
            "description": "From a suggestion (max 300).",
            "schema": {
              "type": "string",
              "example": "ChIJ3Elm"
            }
          },
          {
            "name": "session",
            "in": "query",
            "required": false,
            "description": "Autocomplete session token.",
            "schema": {
              "type": "string",
              "example": "a1b2c3"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a suggested address",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "address": {
                      "address_1": "3 Elm St",
                      "city": "Toronto",
                      "province": "ON",
                      "postcode": "M4M 1A1"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_NO_HOME_DELIVERY, GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "422": {
            "description": "place_id missing"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.address.details",
        "x-graphql": "platformAppGroupBuyAddressDetails",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buys/{code}/address/suggestions": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Suggest home addresses",
        "description": "Signed-in customer of the customer app or MiBox. Suggestions while the buyer types a home address, through the Client's map key (empty without one; data.address_suggestions on the campaign says whether to ask). 404 GROUP_BUY_NO_HOME_DELIVERY when the campaign has no home delivery. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyAddressSuggestions",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "What the buyer typed (max 200).",
            "schema": {
              "type": "string",
              "example": "3 Elm"
            }
          },
          {
            "name": "session",
            "in": "query",
            "required": false,
            "description": "Autocomplete session token (max 64).",
            "schema": {
              "type": "string",
              "example": "a1b2c3"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Suggest home addresses",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "suggestions": [
                      {
                        "place_id": "ChIJ3Elm",
                        "text": "3 Elm St, Toronto, ON"
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_NO_HOME_DELIVERY, GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "422": {
            "description": "q missing"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.address.suggestions",
        "x-graphql": "platformAppGroupBuyAddressSuggestions",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buys/{code}/quote": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Price a group buy order",
        "description": "Signed-in customer of the customer app or MiBox. Prices an order without placing it: group prices × quantities, tax at the store rate, the home delivery fee (D25). Always 200: data.ok false lists errors (codes campaign_closed, item_unavailable, no_items, receive_unavailable, receive_required, address_required) and messages. lines = {campaign item id: quantity}; receive = point:{id} | leader:{group id} | home; leader = the mark of the link; address (home) = {address_1, address_2, city, province, postcode, delivery_instruction}. Coordinates are looked up by the server, never taken from the app. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). The app answer also carries currency (the Client's currency code the amounts are in), next to the web quote's fields. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyQuote",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "lines": {
                  "1": 2
                },
                "receive": "home",
                "address": {
                  "address_1": "3 Elm St",
                  "city": "Toronto",
                  "postcode": "M4M 1A1",
                  "delivery_instruction": "Side door"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Price a group buy order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "ok": true,
                    "errors": [],
                    "messages": [],
                    "units": 2,
                    "subtotal": 10,
                    "delivery_fee": 0,
                    "tax": 1.3,
                    "total": 11.3,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.quote",
        "x-graphql": "platformAppGroupBuyQuote",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buys/{code}/order": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Place a group buy order",
        "description": "Signed-in customer of the customer app or MiBox. Places the order with the account's name, e-mail and phone (and its linked identity) and starts a card hold for the total (D5): 201 with data.order and data.payment {client_secret, publishable_key, merchant_country, merchant_display_name, capture: manual}. Present the Stripe PaymentSheet with the client secret (a manual-capture PaymentIntent: the card is held, charged only if the group forms), then call confirm-payment. Same input as quote, plus note (max 500). 422 GROUP_BUY_ORDER_REFUSED with errors / messages (quote codes plus payment_unavailable, payment_failed). data.order: token, number (store order number), campaign {code, title, status, cutoff_at, expected_delivery_at}, store {id, name}, hold_status (pending | authorized | captured | voided | failed) with hold_label and hold_message, status (the store order: pending_payment until the group forms, then paid / completed / cancelled / refunded), delivery (pickup | home), units, total, currency, place (pickup: name, address, notes, leader) or null, shipment_status, collected_at, collected_via, created_at, web_url; and in detail subtotal, delivery_fee, tax, lines [{name, qty, unit_price, total}], address, at_locker, locker {location, compartment, pickup_code} once a bag waits in a locker cell, can_confirm_received. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyPlaceOrder",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "lines": {
                  "1": 2
                },
                "receive": "point:1",
                "leader": "ANNPORCH01",
                "address": null,
                "note": "Ring the bell"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Place a group buy order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "pending",
                      "hold_label": "Waiting for the card",
                      "hold_message": "The card hold is being confirmed. This page updates by itself.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": true
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    },
                    "payment": {
                      "client_secret": "pi_secret_1",
                      "publishable_key": "pk_test",
                      "merchant_country": "CA",
                      "merchant_display_name": "Fresh Market",
                      "capture": "manual"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "GROUP_BUY_ORDER_REFUSED",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "GROUP_BUY_ORDER_REFUSED",
                  "message": "Choose at least one product.",
                  "errors": [
                    "no_items",
                    "address_required"
                  ],
                  "messages": [
                    "Choose at least one product.",
                    "Enter the delivery address and postal code."
                  ]
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.place",
        "x-graphql": "platformAppGroupBuyPlaceOrder",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-orders/{token}/confirm-payment": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Confirm a group buy card hold",
        "description": "Signed-in customer of the customer app or MiBox. After the payment sheet: reads the hold from Stripe and records it — authorized (the order counts, its stock is taken) or failed / voided (the order is cancelled). Safe to call again: a hold already recorded is left as it is. Answers the order. 404 GROUP_BUY_ORDER_NOT_FOUND for a token of another Client. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyConfirmPayment",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Confirm a group buy card hold",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND or GROUP_BUY_UNAVAILABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.orders.confirm-payment",
        "x-graphql": "platformAppGroupBuyConfirmPayment",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-orders": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "List my group buy orders",
        "description": "Signed-in customer of the customer app or MiBox. The account's group buy orders with this Client, newest first (a hold the card never completed is left out). data.items as in the order detail without the detail fields; data.pagination {current_page, per_page, has_more}. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyOrders",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page, from 1.",
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "1–50, default 20.",
            "schema": {
              "type": "integer",
              "example": 20
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List my group buy orders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                        "number": 1,
                        "campaign": {
                          "code": "FRUITBOX26",
                          "title": "Fruit box",
                          "status": "published",
                          "cutoff_at": "2026-11-07T20:00:00-05:00",
                          "expected_delivery_at": null
                        },
                        "store": {
                          "id": 1,
                          "name": "Fresh Market"
                        },
                        "hold_status": "authorized",
                        "hold_label": "Amount held",
                        "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                        "status": "pending_payment",
                        "delivery": "pickup",
                        "units": 2,
                        "total": 11.3,
                        "currency": "CAD",
                        "place": {
                          "name": "Ann's porch",
                          "address": "9 Oak Ave, Toronto, M6G 1A1",
                          "notes": "Evenings",
                          "leader": true
                        },
                        "shipment_status": "delivered",
                        "collected_at": null,
                        "collected_via": null,
                        "created_at": "2026-11-04T12:00:00-05:00",
                        "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                        "actions": {
                          "can_pay": false
                        }
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "per_page": 20,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.orders.index",
        "x-graphql": "platformAppGroupBuyOrders",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-orders/{token}": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get a group buy order",
        "description": "Signed-in customer of the customer app or MiBox. One order by its token; a hold still pending is read from Stripe first (as the web order page does). data.order: token, number (store order number), campaign {code, title, status, cutoff_at, expected_delivery_at}, store {id, name}, hold_status (pending | authorized | captured | voided | failed) with hold_label and hold_message, status (the store order: pending_payment until the group forms, then paid / completed / cancelled / refunded), delivery (pickup | home), units, total, currency, place (pickup: name, address, notes, leader) or null, shipment_status, collected_at, collected_via, created_at, web_url; and in detail subtotal, delivery_fee, tax, lines [{name, qty, unit_price, total}], address, at_locker, locker {location, compartment, pickup_code} once a bag waits in a locker cell, can_confirm_received. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyOrder",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a group buy order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": "delivered",
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": true
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND or GROUP_BUY_UNAVAILABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.orders.show",
        "x-graphql": "platformAppGroupBuyOrder",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-orders/{token}/pay": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Resume a group buy card hold",
        "description": "Signed-in customer of the customer app or MiBox. Resume the card hold of an order whose buyer closed the payment sheet (hold_status pending). While Stripe still lets the order's PaymentIntent be confirmed (requires_payment_method, requires_confirmation, requires_action) its client secret is answered again (reused_intent true); otherwise (cancelled or unreadable) a new manual-capture hold is started with the store's Stripe account, as placing the order does, and replaces the old one on the order (reused_intent false). data: order (as the order call) and payment {client_secret, publishable_key, merchant_country, merchant_display_name, capture: manual}, the same block as placing the order; present the PaymentSheet, then call confirm-payment. Allowed when order.actions.can_pay is true: the hold is pending, the campaign is still published and before its cutoff, and the order's group is still open (a hold started before the cutoff outlasts the merchant's decision window, GROUP-BUY-DESIGN D5 / D18). 409 GROUP_BUY_NOT_AWAITING_HOLD otherwise. 409 GROUP_BUY_ALREADY_HELD with data.order when Stripe shows the card already held (or being held): the hold is recorded as confirm-payment would, and no second hold is started. 422 PAYMENT_ERROR when no hold could be started. 404 GROUP_BUY_ORDER_NOT_FOUND for a token of another Client. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyOrderPay",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resume a group buy card hold",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "pending",
                      "hold_label": "Waiting for the card",
                      "hold_message": "Complete the card payment to join the group.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": true
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    },
                    "payment": {
                      "client_secret": "pi_3Q_secret_abc",
                      "publishable_key": "pk_live_123",
                      "merchant_country": "CA",
                      "merchant_display_name": "Fresh Market",
                      "capture": "manual"
                    },
                    "reused_intent": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "GROUP_BUY_NOT_AWAITING_HOLD (the hold is no longer pending, or the campaign / group no longer takes orders), or GROUP_BUY_ALREADY_HELD with data.order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "GROUP_BUY_ALREADY_HELD",
                  "message": "The card is already held for this order.",
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "PAYMENT_ERROR (no hold could be started)"
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND or GROUP_BUY_UNAVAILABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.orders.pay",
        "x-graphql": "platformAppGroupBuyOrderPay",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-orders/{token}/received": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Mark a group buy order received",
        "description": "Signed-in customer of the customer app or MiBox. The buyer says the goods arrived (D27): allowed once they are on their way or at the pickup point (can_confirm_received), never for a bag in a locker cell (collected with the pickup code). Answers the order. 422 GROUP_BUY_NOT_RECEIVABLE otherwise. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyOrderReceived",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mark a group buy order received",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": "delivered",
                      "collected_at": "2026-11-04T12:00:00-05:00",
                      "collected_via": "leader",
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "GROUP_BUY_NOT_RECEIVABLE"
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.orders.received",
        "x-graphql": "platformAppGroupBuyOrderReceived",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buys/{code}/lead": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get leading a group buy",
        "description": "Signed-in customer of the customer app or MiBox. For a published campaign that takes leaders, or a self-pick plan: campaign, leader_policy (any | approved), leader (the customer's application with status pending | approved | rejected | disabled and pickup details) or null, may_lead, can_apply (false once disabled), group {id, mark, share_url} once opened — share_url is the campaign link on the Client's white-label host with ?leader={mark} —, self_pick {items, earliest_cutoff, latest_cutoff, timezone} for a plan the leader may start a campaign from, commission_rates [{id, name, group_price, commission_mode percentage | fixed, commission_value}] (D10). Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). currency: the Client's currency code, which the amounts (group prices, commission) are in. Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyLead",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get leading a group buy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "campaign",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "leader_policy": "any",
                    "leader": null,
                    "may_lead": false,
                    "can_apply": true,
                    "group": null,
                    "self_pick": null,
                    "currency": "CAD",
                    "commission_rates": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "commission_mode": "percentage",
                        "commission_value": 10
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.lead",
        "x-graphql": "platformAppGroupBuyLead",
        "x-capability": "group_buy"
      },
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Apply to lead a group buy",
        "description": "Signed-in customer of the customer app or MiBox. Applies to the campaign's store with the address buyers collect from, or changes the details of a pending or approved application; a rejected applicant applies again. Fields pickup_name (required, max 120), address (required), address_2, city, province, postcode (required), phone, pickup_notes. 422 VALIDATION_FAILED with errors per field (also for a disabled leader: errors.status). Answers the lead view. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). currency: the Client's currency code, which the amounts (group prices, commission) are in. Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyLeadApply",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "pickup_name": "Ann's porch",
                "address": "9 Oak Ave",
                "city": "Toronto",
                "postcode": "M6G 1A1",
                "phone": "4165550111",
                "pickup_notes": "Evenings"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Apply to lead a group buy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "campaign",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "leader_policy": "any",
                    "leader": {
                      "status": "pending",
                      "pickup_name": "Ann's porch",
                      "address": "9 Oak Ave",
                      "address_2": null,
                      "city": "Toronto",
                      "province": null,
                      "postcode": "M6G 1A1",
                      "phone": "4165550111",
                      "pickup_notes": "Evenings",
                      "decision_note": null
                    },
                    "may_lead": true,
                    "can_apply": true,
                    "group": null,
                    "self_pick": null,
                    "currency": "CAD",
                    "commission_rates": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "commission_mode": "percentage",
                        "commission_value": 10
                      }
                    ]
                  }
                }
              }
            }
          },
          "422": {
            "description": "VALIDATION_FAILED"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.lead.apply",
        "x-graphql": "platformAppGroupBuyLeadApply",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buys/{code}/lead/open": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Open a group buy group",
        "description": "Signed-in customer of the customer app or MiBox. Opens the customer's group in the campaign (once; again answers the same group) with its leader mark; share data.group.share_url. 403 GROUP_BUY_LEADER_NOT_ALLOWED when the customer may not lead (approved leaders only and not approved yet, disabled, or a self-pick plan). Answers the lead view. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). currency: the Client's currency code, which the amounts (group prices, commission) are in. Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyLeadOpen",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Open a group buy group",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "campaign",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "leader_policy": "any",
                    "leader": {
                      "status": "pending",
                      "pickup_name": "Ann's porch",
                      "address": "9 Oak Ave",
                      "address_2": null,
                      "city": "Toronto",
                      "province": null,
                      "postcode": "M6G 1A1",
                      "phone": "4165550111",
                      "pickup_notes": "Evenings",
                      "decision_note": null
                    },
                    "may_lead": true,
                    "can_apply": true,
                    "group": {
                      "id": 1,
                      "mark": "ANNPORCH01",
                      "share_url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26%3Fleader%3DANNPORCH01"
                        }
                      }
                    },
                    "self_pick": null,
                    "commission_rates": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "commission_mode": "percentage",
                        "commission_value": 10
                      }
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.lead.open",
        "x-graphql": "platformAppGroupBuyLeadOpen",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buys/{code}/lead/start": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Start a campaign from a self-pick plan",
        "description": "Signed-in customer of the customer app or MiBox. D31: on a self-pick plan the leader may use, starts the leader's own campaign: item_ids (the plan's items), cutoff_at and expected_delivery_at as Y-m-d\\TH:i on the store's clock (within self_pick.earliest_cutoff … latest_cutoff), optional title. Open to buyers at once (D32) with the leader's group opened; 201 with the new campaign's lead view. 422 VALIDATION_FAILED, 403 GROUP_BUY_LEADER_NOT_ALLOWED, 404 GROUP_BUY_NOT_FOUND for a campaign that is not a plan. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). currency: the Client's currency code, which the amounts (group prices, commission) are in. Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyLeadStart",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "item_ids": [
                  1
                ],
                "cutoff_at": "2026-11-06T20:00",
                "expected_delivery_at": "2026-11-08T10:00",
                "title": "Weekly fruit"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Start a campaign from a self-pick plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "leader",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "leader_policy": "any",
                    "leader": {
                      "status": "pending",
                      "pickup_name": "Ann's porch",
                      "address": "9 Oak Ave",
                      "address_2": null,
                      "city": "Toronto",
                      "province": null,
                      "postcode": "M6G 1A1",
                      "phone": "4165550111",
                      "pickup_notes": "Evenings",
                      "decision_note": null
                    },
                    "may_lead": true,
                    "can_apply": true,
                    "group": {
                      "id": 1,
                      "mark": "ANNPORCH01",
                      "share_url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26%3Fleader%3DANNPORCH01"
                        }
                      }
                    },
                    "self_pick": null,
                    "commission_rates": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "commission_mode": "percentage",
                        "commission_value": 10
                      }
                    ]
                  }
                }
              }
            }
          },
          "422": {
            "description": "VALIDATION_FAILED"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.lead.start",
        "x-graphql": "platformAppGroupBuyLeadStart",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-leading": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "List the groups I lead",
        "description": "Signed-in customer of the customer app or MiBox. The groups the customer leads at this Client, newest first: id, mark, status, campaign, orders and units that count (held or charged), share_url while the campaign is published; templates = the self-pick plans the customer may start a campaign from. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Group status values: open (taking orders until the campaign closes), formed (going ahead; its holds are captured), short (short of a threshold, waiting for the merchant's decision), cancelled (did not go ahead; its holds are released); status_label is its translated name, as the store console shows it. currency: the Client's currency code, which the amounts (group prices, commission) are in. Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyLeading",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the groups I lead",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "groups": [
                      {
                        "id": 1,
                        "mark": "ANNPORCH01",
                        "status": "open",
                        "status_label": "Open",
                        "campaign": {
                          "code": "FRUITBOX26",
                          "kind": "campaign",
                          "title": "Fruit box",
                          "description": null,
                          "status": "published",
                          "orderable": true,
                          "opens_at": "2026-11-03T08:00:00-05:00",
                          "cutoff_at": "2026-11-07T20:00:00-05:00",
                          "expected_delivery_at": null,
                          "takes_leaders": true,
                          "allow_pickup": true,
                          "allow_home_delivery": true,
                          "home_fee": {
                            "mode": "fixed",
                            "fee": 7,
                            "free_over": 30
                          },
                          "store": {
                            "id": 1,
                            "name": "Fresh Market",
                            "slug": "fresh-market",
                            "timezone": "America/Toronto"
                          },
                          "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                          "share": {
                            "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                            "title": "Fruit box",
                            "channels": [
                              "system",
                              "wechat",
                              "whatsapp",
                              "facebook",
                              "x",
                              "email",
                              "copy",
                              "qr"
                            ],
                            "links": {
                              "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                            }
                          }
                        },
                        "orders": 1,
                        "units": 2,
                        "share_url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                        "share": {
                          "url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                          "title": "Fruit box",
                          "channels": [
                            "system",
                            "wechat",
                            "whatsapp",
                            "facebook",
                            "x",
                            "email",
                            "copy",
                            "qr"
                          ],
                          "links": {
                            "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26%3Fleader%3DANNPORCH01"
                          }
                        }
                      }
                    ],
                    "currency": "CAD",
                    "templates": []
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.leading",
        "x-graphql": "platformAppGroupBuyLeading",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-leading/{groupId}": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get a group I lead",
        "description": "Signed-in customer of the customer app or MiBox. One of the customer's groups: group {id, mark, status, pickup_name, share_url}, campaign, households [{id, number, name, delivery, units, hold_status, lines, shipment_status, collected_at, collected_via, can_mark_collected, commission}], totals {orders, units, commission}, commission_rates. commission = what the leader earns on the order now (D10: per product, a percentage of what the buyer paid or a fixed amount per unit, refunds deducted); it is booked when the group is charged. 404 GROUP_BUY_GROUP_NOT_FOUND for a group the customer does not lead. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Group status values: open (taking orders until the campaign closes), formed (going ahead; its holds are captured), short (short of a threshold, waiting for the merchant's decision), cancelled (did not go ahead; its holds are released); status_label is its translated name, as the store console shows it. Each household also has hold_label: the translated name of hold_status, the wording of the buyer's order page (hold_status pending, authorized, captured, voided, failed). currency: the Client's currency code, which the amounts (group prices, commission) are in. Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyLeadingGroup",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "description": "The group id.",
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a group I lead",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "group": {
                      "id": 1,
                      "mark": "ANNPORCH01",
                      "status": "open",
                      "status_label": "Open",
                      "pickup_name": "Ann's porch",
                      "share_url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26%3Fleader%3DANNPORCH01"
                        }
                      }
                    },
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "campaign",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "households": [
                      {
                        "id": 1,
                        "number": 1,
                        "name": "Ann",
                        "delivery": "pickup",
                        "units": 2,
                        "hold_status": "authorized",
                        "hold_label": "Amount held",
                        "lines": [
                          {
                            "name": "Apples",
                            "qty": 2
                          }
                        ],
                        "shipment_status": "delivered",
                        "collected_at": null,
                        "collected_via": null,
                        "can_mark_collected": true,
                        "commission": 1
                      }
                    ],
                    "totals": {
                      "orders": 1,
                      "units": 2,
                      "commission": 1
                    },
                    "currency": "CAD",
                    "commission_rates": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "commission_mode": "percentage",
                        "commission_value": 10
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_GROUP_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.leading.group",
        "x-graphql": "platformAppGroupBuyLeadingGroup",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/group-buy-leading/{groupId}/orders/{orderId}/collected": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Mark a household collected",
        "description": "Signed-in customer of the customer app or MiBox. D27: the leader confirms a household collected its bag at the leader's pickup point, once the bags arrived (can_mark_collected). The order completes and the commission is approved (D19). Answers the group. 422 GROUP_BUY_NOT_COLLECTABLE (not arrived, or in a locker cell), 404 GROUP_BUY_ORDER_NOT_FOUND / GROUP_BUY_GROUP_NOT_FOUND. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Group status values: open (taking orders until the campaign closes), formed (going ahead; its holds are captured), short (short of a threshold, waiting for the merchant's decision), cancelled (did not go ahead; its holds are released); status_label is its translated name, as the store console shows it. Each household also has hold_label: the translated name of hold_status, the wording of the buyer's order page (hold_status pending, authorized, captured, voided, failed). currency: the Client's currency code, which the amounts (group prices, commission) are in. Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGroupBuyLeadingCollected",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "description": "The group id.",
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "description": "The household's order id (households[].id).",
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mark a household collected",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "group": {
                      "id": 1,
                      "mark": "ANNPORCH01",
                      "status": "open",
                      "status_label": "Open",
                      "pickup_name": "Ann's porch",
                      "share_url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26?leader=ANNPORCH01",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26%3Fleader%3DANNPORCH01"
                        }
                      }
                    },
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "campaign",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "households": [
                      {
                        "id": 1,
                        "number": 1,
                        "name": "Ann",
                        "delivery": "pickup",
                        "units": 2,
                        "hold_status": "authorized",
                        "hold_label": "Amount held",
                        "lines": [
                          {
                            "name": "Apples",
                            "qty": 2
                          }
                        ],
                        "shipment_status": "delivered",
                        "collected_at": "2026-11-04T12:00:00-05:00",
                        "collected_via": "leader",
                        "can_mark_collected": false,
                        "commission": 1
                      }
                    ],
                    "totals": {
                      "orders": 1,
                      "units": 2,
                      "commission": 1
                    },
                    "commission_rates": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "commission_mode": "percentage",
                        "commission_value": 10
                      }
                    ]
                  }
                }
              }
            }
          },
          "422": {
            "description": "GROUP_BUY_NOT_COLLECTABLE"
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND or GROUP_BUY_GROUP_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.group-buy.leading.collected",
        "x-graphql": "platformAppGroupBuyLeadingCollected",
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/bootstrap": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Bootstrap a client-assigned app",
        "description": "Returns public branding, effective capabilities, service contracts and version policy. The client code identifies configuration only and is not an authorization credential. settings.home.quick_actions lists the home screen shortcut ids (send, return, store, lockers, luggage, handover, pay, wallet) in the Client's order, without the ones it hid; the app shows a shortcut only while its capability is on. locales lists the language codes the app offers (en, chs, cht, de, es, fr, it, nl, pt, sr, hu, pl, sk, cs), in the order the app lists them; it is the same for every client of an app. For the SuperRoute customer app (appCode customer), settings.web.portal_enabled says whether the client runs the web portal, and settings has no home section. Additive: client.country (ISO 3166 alpha-2, CA when unset) and client.currency (CAD when unset), the client's defaults for forms and prices. Answered exactly as the internal route.",
        "operationId": "platformAppBootstrap",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "web: the browser portal (/portal); it has no upgrade policy.",
            "schema": {
              "type": "string",
              "enum": [
                "ios",
                "android",
                "web"
              ]
            }
          },
          {
            "name": "app_version",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "1.0.0"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Effective public app configuration",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "app": {
                      "code": "mibox",
                      "name": "MiBox",
                      "type": "customer",
                      "schema_version": 1
                    },
                    "client": {
                      "code": "n4x7q2g8w9r3k6m1p5t0z8ab",
                      "display_name": "Mili Express",
                      "country": "CA",
                      "currency": "CAD"
                    },
                    "configuration_version": 3,
                    "capabilities": {
                      "auth.google": true,
                      "wallet.balance": true,
                      "locker.pickup": true
                    },
                    "locales": [
                      "en",
                      "chs",
                      "cht",
                      "de",
                      "es",
                      "fr",
                      "it",
                      "nl",
                      "pt",
                      "sr",
                      "hu",
                      "pl",
                      "sk",
                      "cs"
                    ],
                    "authentication": {
                      "methods": {
                        "google": true,
                        "email": true,
                        "registration": true
                      },
                      "google": {
                        "server_client_id": "shared-web-oauth-client.apps.googleusercontent.com"
                      },
                      "registration": {
                        "enabled": true,
                        "phone_verification_required": true,
                        "sms_configured": true,
                        "default_phone_region": "CA",
                        "requires_approval": false,
                        "code_length": 6,
                        "resend_after": 60
                      }
                    },
                    "services": {
                      "identity": {
                        "source_of_truth": "superroute",
                        "shared_with_web": true
                      },
                      "wallet": {
                        "source_of_truth": "superroute",
                        "ledger_mode": "existing_customer_account"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The app or client assignment is not currently available"
          },
          "404": {
            "description": "The app/client context does not exist"
          },
          "422": {
            "description": "Invalid platform or app version"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.bootstrap",
        "x-graphql": "platformAppBootstrap",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/track": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Track any code (guest)",
        "description": "Universal tracking (docs/APP-UNIVERSAL-TRACKING-DESIGN.md): one code of this Client in, whatever it is — `kind` parcel (tracking number), moving (moving code), storage (storage code), return (return code), shipping (shipping order code) or carrier_package (carrier tracking number). `tracking` is the OTEP public view (as /oteptrack); its `details` (addresses, dates, proof of delivery) and `summary.code` (pickup code) are present once `verified`. Send `answer` (last 4 digits of a phone on the shipment, or its postcode) to verify; `can_verify` says whether that is possible. A storage, return or shipping code is the drop-off code the sender holds, so `summary.code` is shown for those. `wallet` holds absolute Apple (.pkpass) and Google (save link) card links valid 2 h, or null when the Client has wallet cards off or the shipment offers no card. Errors: 404 TRACKING_NOT_FOUND (unknown code), 422 TRACKING_VERIFY_FAILED (wrong answer), 422 TRACKING_INVALID, 429 TRACKING_TOO_MANY. Public, no sign-in. Pickup codes are never answered here. Needs the tracking capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestTrack",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "identifier"
                ],
                "properties": {
                  "identifier": {
                    "type": "string",
                    "maxLength": 100,
                    "example": "R8K2Q7"
                  },
                  "answer": {
                    "type": "string",
                    "maxLength": 20,
                    "example": "4821"
                  },
                  "locale": {
                    "type": "string",
                    "example": "en"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What the code is and where it stands",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "kind": "return",
                    "identifier": "R8K2Q7",
                    "owned": false,
                    "verified": false,
                    "can_verify": true,
                    "summary": {
                      "stage": "send",
                      "status": "awaiting_dropoff",
                      "reference": "RMA-1042",
                      "place": null,
                      "deadline": null,
                      "code": "R8K2Q7"
                    },
                    "tracking": {
                      "otep_version": "0.1",
                      "profile": "parcel",
                      "subject": {
                        "identifier": "R8K2Q7",
                        "profile": "parcel"
                      },
                      "current_status": "booking_confirmed",
                      "current_phase": "pre_shipment",
                      "delivered": false,
                      "events": [
                        {
                          "occurred_at": "2026-10-18T09:12:00-04:00",
                          "status_code": "information_submitted",
                          "phase": "pre_shipment",
                          "location": null
                        },
                        {
                          "occurred_at": "2026-10-18T09:40:00-04:00",
                          "status_code": "booking_confirmed",
                          "phase": "pre_shipment",
                          "location": null
                        }
                      ]
                    },
                    "wallet": {
                      "apple": "https://track.example.com/wallet-card/en/return_request/1042/apple?code=1&expires=1760800000&signature=...",
                      "google": "https://track.example.com/wallet-card/en/return_request/1042/google?code=1&expires=1760800000&signature=..."
                    },
                    "pickup_id": null
                  }
                }
              }
            }
          },
          "404": {
            "description": "TRACKING_NOT_FOUND, or the App / Client is not available"
          },
          "422": {
            "description": "TRACKING_INVALID or TRACKING_VERIFY_FAILED"
          },
          "429": {
            "description": "TRACKING_TOO_MANY"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry tracking"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.track",
        "x-graphql": "platformAppGuestTrack",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "tracking"
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/locker-open": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Open the next door of a guest's paid locker pickup",
        "description": "Open the next door of a guest's paid locker pickup. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. 409 NOT_A_LOCKER_ORDER, 404 CABINET_NOT_FOUND, 422/409 with code of the refusal (door not opened). Needs the locker.remote_open capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderLockerOpen",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Door 3 opened: Cola",
                  "door_opened": true,
                  "refund_available": false,
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry locker.remote_open"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.store-orders.locker-open",
        "x-graphql": "platformAppGuestStoreOrderLockerOpen",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "locker.remote_open"
      }
    },
    "/app/v1/registration/clients": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List the Clients that accept new customer registrations",
        "description": "Public and unauthenticated: this is the first call an app makes for a person who has no account yet, and it answers nothing account-specific. Only Clients whose assignment is effective, whose customer role is enabled and whose auth.registration capability is on are listed, so every entry is a door that will actually accept a sign-up. When `count` is 1 the app can skip the picker and open the registration form directly. Answered exactly as the internal route.",
        "operationId": "platformAppRegistrationClients",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The Clients open to registration for this app.",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "data": {
                    "app": {
                      "code": "mibox",
                      "name": "MiBox"
                    },
                    "count": 2,
                    "items": [
                      {
                        "client_code": "n4x7q2g8w9r3k6m1p5t0z8ab",
                        "display_name": "MiBox Toronto",
                        "logo_url": "https://cdn.example.com/mibox-to.png",
                        "primary_color": "#146C94",
                        "support_email": "support@example.com",
                        "privacy_url": "https://example.com/privacy",
                        "terms_url": "https://example.com/terms",
                        "requires_approval": true,
                        "phone_verification_required": true,
                        "sms_configured": true,
                        "default_phone_region": "CA",
                        "authentication": {
                          "google": true,
                          "google_server_client_id": "1234567890-abc.apps.googleusercontent.com",
                          "apple": true
                        }
                      },
                      {
                        "client_code": "b8k2m5q9w1e4r7t0y3u6i9op",
                        "display_name": "MiBox Vancouver",
                        "logo_url": null,
                        "primary_color": "#146C94",
                        "support_email": null,
                        "privacy_url": null,
                        "terms_url": null,
                        "requires_approval": false,
                        "phone_verification_required": false,
                        "sms_configured": false,
                        "default_phone_region": "CA",
                        "authentication": {
                          "google": false,
                          "google_server_client_id": "1234567890-abc.apps.googleusercontent.com",
                          "apple": false
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "App not found or not active"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.registration.clients",
        "x-graphql": "platformAppRegistrationClients",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/registration/phone/request": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Request a registration phone verification code",
        "description": "Creates a five-minute, App- and Client-scoped verification challenge and sends a six-digit code using the selected Client's SMS provider. Codes are rate limited and never returned by the API. Needs the auth.registration capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppRequestRegistrationCode",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone"
                ],
                "properties": {
                  "phone": {
                    "type": "string",
                    "maxLength": 50
                  },
                  "locale": {
                    "type": "string",
                    "example": "en"
                  }
                }
              },
              "example": {
                "phone": "+1 416 555 0100",
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification challenge created",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "message": "A verification code was sent.",
                  "challenge_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
                  "phone_e164": "+14****0100",
                  "expires_in": 300,
                  "resend_after": 60
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry auth.registration"
          },
          "422": {
            "description": "Invalid phone number"
          },
          "429": {
            "description": "Code request rate limit exceeded"
          },
          "503": {
            "description": "Client SMS service is not configured or delivery failed"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.registration.phone.request",
        "x-graphql": "platformAppRequestRegistrationCode",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "auth.registration"
      }
    },
    "/app/v1/clients/{clientCode}/registration/email/request": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Request a registration email verification code",
        "description": "For an app whose Clients choose the sign-up verification channel (the SuperRoute customer app, appCode customer) and a Client that chose email (bootstrap authentication.registration.verification_channel). Creates a ten-minute, App- and Client-scoped challenge and emails a six-digit code. The answer is the same whether or not the address already has an account: an address that has one is sent no code, only a note that it is registered, so the challenge cannot be completed. Codes are never returned by the API. Needs the auth.registration capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppRequestRegistrationEmailCode",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 255
                  },
                  "locale": {
                    "type": "string",
                    "example": "en"
                  }
                }
              },
              "example": {
                "email": "jane.doe@example.com",
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification challenge created (the same answer for a registered address)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppEmailChallenge"
                },
                "example": {
                  "result": true,
                  "message": "A verification email was sent.",
                  "challenge_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
                  "email": "j*******@example.com",
                  "expires_in": 600,
                  "resend_after": 60
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry auth.registration"
          },
          "422": {
            "description": "Invalid email address"
          },
          "429": {
            "description": "EMAIL_VERIFICATION_RATE_LIMITED: another code for this address within 60 seconds, or the request rate limit"
          },
          "503": {
            "description": "EMAIL_DELIVERY_FAILED: the email could not be sent"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.registration.email.request",
        "x-graphql": "platformAppRequestRegistrationEmailCode",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "auth.registration"
      }
    },
    "/app/v1/clients/{clientCode}/registration/complete": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Register a Client customer",
        "description": "Creates the normal Superroute User and Customer records and either issues an app session or returns a pending-review result. Existing accounts are never overwritten or duplicated.\n\nTwo shapes, chosen by the Client's `registration.require_phone_verification` setting (published as `authentication.registration.phone_verification_required` on bootstrap). When it is on, send `challenge_id` and `code` from /registration/phone/request and the phone is recorded as verified. When it is off, send `phone` instead and the number is stored unverified. A challenge is always honoured if supplied.\n\nFor an app whose Clients choose the verification channel (the SuperRoute customer app), a challenge is always required and the Client's channel (`authentication.registration.verification_channel` on bootstrap) decides: phone as above, or email — send `channel: email` with `challenge_id` and `code` from /registration/email/request, the same `email`, and `phone` (a contact number, stored unverified and never compared with other accounts); the answer then also carries `email_verified: true`. `channel` defaults to phone.\n\nOptionally send `google_id_token` and/or `apple_id_token` (with `apple_authorization_code` and `apple_name`) to link the Google / Apple account the person signed in with; the answer lists what was linked in `linked_providers`.\n\nThe address is mandatory in both shapes. The new account starts from the customer template the Client selected for this app, or from the business default template when it selected none. Needs the auth.registration capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppRegisterCustomer",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "email",
                  "password",
                  "password_confirmation",
                  "address",
                  "city",
                  "postcode",
                  "country",
                  "device_id",
                  "device_platform"
                ],
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "phone",
                      "email"
                    ],
                    "nullable": true,
                    "description": "The channel the challenge came from. Defaults to phone."
                  },
                  "challenge_id": {
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 64,
                    "nullable": true,
                    "description": "Required when the Client requires SMS verification. Send with `code`."
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[0-9]{6}$",
                    "nullable": true,
                    "description": "Required when the Client requires SMS verification. Send with `challenge_id`."
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string",
                    "format": "password",
                    "minLength": 8
                  },
                  "password_confirmation": {
                    "type": "string",
                    "format": "password"
                  },
                  "country": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "locale": {
                    "type": "string",
                    "nullable": true
                  },
                  "device_id": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "device_platform": {
                    "type": "string",
                    "enum": [
                      "ios",
                      "android",
                      "web"
                    ],
                    "description": "web: the browser portal (/portal)."
                  },
                  "app_version": {
                    "type": "string",
                    "nullable": true
                  },
                  "google_id_token": {
                    "type": "string",
                    "maxLength": 20000,
                    "nullable": true,
                    "description": "Optional. A Google ID token from the app's Google sign-in; the Google account is linked to the new account. Needs the auth.google capability; refused with 409 GOOGLE_ACCOUNT_LINK_CONFLICT when that Google account is already linked, before any verification code is used."
                  },
                  "apple_id_token": {
                    "type": "string",
                    "maxLength": 20000,
                    "nullable": true,
                    "description": "Optional. An Apple identity token from Sign in with Apple; the Apple ID is linked to the new account. Needs the auth.apple capability; refused with 409 APPLE_ACCOUNT_LINK_CONFLICT when that Apple ID is already linked, before any verification code is used."
                  },
                  "apple_authorization_code": {
                    "type": "string",
                    "maxLength": 2000,
                    "nullable": true,
                    "description": "Optional, with apple_id_token: the authorization code, kept so an account closure can revoke the Apple authorisation."
                  },
                  "apple_name": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Optional, with apple_id_token: the name Apple gave the device on the first sign-in."
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 50,
                    "nullable": true,
                    "description": "Required when no challenge is sent; stored unverified."
                  },
                  "address": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "address_2": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "city": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "province": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "postcode": {
                    "type": "string",
                    "maxLength": 255
                  }
                }
              },
              "example": {
                "challenge_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
                "code": "123456",
                "name": "MiBox Customer",
                "email": "customer@example.com",
                "password": "account-password",
                "password_confirmation": "account-password",
                "address": "123 King Street West",
                "address_2": "Unit 5",
                "city": "Toronto",
                "province": "ON",
                "postcode": "M5H 1A1",
                "country": "Canada",
                "device_id": "0f3d1c43-7f53-4c16-ae90-62a2bc921812",
                "device_platform": "ios",
                "app_version": "1.0.0"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customer registered. Returns either a Passport app session or REGISTRATION_PENDING_REVIEW.",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "message": "Registration and phone verification completed.",
                  "phone_verified": true,
                  "requires_approval": false,
                  "access_token": "passport-access-token",
                  "token_type": "Bearer",
                  "linked_providers": []
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry auth.registration"
          },
          "409": {
            "description": "Existing account, linked phone, concurrent registration, or GOOGLE_ACCOUNT_LINK_CONFLICT / APPLE_ACCOUNT_LINK_CONFLICT for a Google / Apple account already linked to another account"
          },
          "410": {
            "description": "Verification challenge expired"
          },
          "422": {
            "description": "Invalid request, missing address, invalid verification code, or PHONE_VERIFICATION_REQUIRED when the Client requires SMS verification and no challenge was sent"
          },
          "429": {
            "description": "Verification attempt limit exceeded"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.registration.complete",
        "x-graphql": "platformAppRegisterCustomer",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "auth.registration"
      }
    },
    "/app/v1/account-closure/withdraw": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Withdraw a pending account closure request",
        "description": "Unauthenticated by necessity: an open closure request suspends the account and revokes its tokens, so requiring a session would make the request impossible to take back. The one-shot `withdrawal_token` is the credential; it is returned once by the closure request itself, again in the notice email's link, and again in the 403 ACCOUNT_CLOSURE_PENDING body when a correct password is refused at sign-in. Withdrawing restores the account to exactly the status it held before the request. Answered exactly as the internal route.",
        "operationId": "platformAppWithdrawAccountClosure",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "withdrawal_token"
                ],
                "properties": {
                  "withdrawal_token": {
                    "type": "string",
                    "maxLength": 191
                  }
                }
              },
              "example": {
                "withdrawal_token": "one-shot-withdrawal-token"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request was withdrawn and the account restored.",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "message": "The account closure request has been withdrawn.",
                  "data": {
                    "id": 42,
                    "status": "cancelled",
                    "requested_at": "2026-09-05T10:00:00+00:00",
                    "cancelled_at": "2026-09-05T12:00:00+00:00",
                    "completed_at": null,
                    "handled_at": null,
                    "reason": "Moving away",
                    "decision_reason": null,
                    "requires_review": true
                  }
                }
              }
            }
          },
          "404": {
            "description": "No pending closure request matches this token"
          },
          "422": {
            "description": "Invalid request"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.account-closure.withdraw",
        "x-graphql": "platformAppWithdrawAccountClosure",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/links/resolve": {
      "get": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "What a scanned link of the client opens in the app",
        "description": "What a scanned link of the client opens in the app: store, store_table, store_category, product, mall, mall_category, group_buy or unknown. Accepts the client's white-label host and the platform host (mall by /m/{code}); kind is store | store_table | store_category (slug, category_id: a category page of the multi-page style, added with docs/STORE-STYLES-DESIGN.md P2) | product | mall (page home|stores|search|group_buy) | mall_category | group_buy (campaign_code, leader_code) | unknown. 404 APP_CONTEXT_NOT_FOUND for an unknown app/client (guest). Answered exactly as the internal route.",
        "operationId": "platformAppLinkResolve",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "https://shop.example.com/s/bistro/t/5"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "kind": "store_table",
                    "slug": "bistro",
                    "table_code": "T5",
                    "campaign_code": null,
                    "leader_code": null,
                    "category_id": null,
                    "product_id": null,
                    "page": null
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "APP_CONTEXT_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.links.resolve",
        "x-graphql": "platformAppLinkResolve"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buys/{code}": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get a group buy campaign as a guest",
        "description": "Public: no sign-in token is read. Same answer as the signed-in call, with guest_verification_channel (email | phone): the contact a guest verifies before ordering. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Added: share — next to a campaign's web_url and a group's share_url, how the store lets buyers share that link, null while it offers no channel or there is no link: {url, title, channels, links}, the same shape and channels as the product answer's share. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuy",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "leader",
            "in": "query",
            "required": false,
            "description": "The leader mark of a shared link.",
            "schema": {
              "type": "string",
              "example": "ANNPORCH01"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a group buy campaign as a guest",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "campaign": {
                      "code": "FRUITBOX26",
                      "kind": "campaign",
                      "title": "Fruit box",
                      "description": null,
                      "status": "published",
                      "orderable": true,
                      "opens_at": "2026-11-03T08:00:00-05:00",
                      "cutoff_at": "2026-11-07T20:00:00-05:00",
                      "expected_delivery_at": null,
                      "takes_leaders": true,
                      "allow_pickup": true,
                      "allow_home_delivery": true,
                      "home_fee": {
                        "mode": "fixed",
                        "fee": 7,
                        "free_over": 30
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market",
                        "slug": "fresh-market",
                        "timezone": "America/Toronto"
                      },
                      "web_url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                      "share": {
                        "url": "https://shop.example.com/portal/group-buy/FRUITBOX26",
                        "title": "Fruit box",
                        "channels": [
                          "system",
                          "wechat",
                          "whatsapp",
                          "facebook",
                          "x",
                          "email",
                          "copy",
                          "qr"
                        ],
                        "links": {
                          "whatsapp": "https://wa.me/?text=Fruit%20box%20https%3A%2F%2Fshop.example.com%2Fportal%2Fgroup-buy%2FFRUITBOX26"
                        }
                      }
                    },
                    "items": [
                      {
                        "id": 1,
                        "name": "Apples",
                        "group_price": 5,
                        "regular_price": 6
                      }
                    ],
                    "pickup": [
                      {
                        "key": "leader:1",
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      {
                        "key": "point:1",
                        "name": "Library",
                        "address": "12 King St, Toronto, M5H 2N2",
                        "notes": "Sat 10-12",
                        "leader": false
                      }
                    ],
                    "home": true,
                    "leader": null,
                    "address_suggestions": false,
                    "currency": "CAD",
                    "tax_rate": 13,
                    "guest_verification_channel": "email"
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.show",
        "x-graphql": "platformAppGuestGroupBuy",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buys/{code}/address/details": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get a suggested address for a guest",
        "description": "Public: no sign-in token is read. As the signed-in call. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyAddressDetails",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "place_id",
            "in": "query",
            "required": true,
            "description": "From a suggestion.",
            "schema": {
              "type": "string",
              "example": "ChIJ3Elm"
            }
          },
          {
            "name": "session",
            "in": "query",
            "required": false,
            "description": "Autocomplete session token.",
            "schema": {
              "type": "string",
              "example": "a1b2c3"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a suggested address for a guest",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "address": {
                      "address_1": "3 Elm St",
                      "city": "Toronto",
                      "province": "ON",
                      "postcode": "M4M 1A1"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_NO_HOME_DELIVERY"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.address.details",
        "x-graphql": "platformAppGuestGroupBuyAddressDetails",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buys/{code}/address/suggestions": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Suggest home addresses to a guest",
        "description": "Public: no sign-in token is read. As the signed-in call. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyAddressSuggestions",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "What the guest typed.",
            "schema": {
              "type": "string",
              "example": "3 Elm"
            }
          },
          {
            "name": "session",
            "in": "query",
            "required": false,
            "description": "Autocomplete session token.",
            "schema": {
              "type": "string",
              "example": "a1b2c3"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Suggest home addresses to a guest",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "suggestions": [
                      {
                        "place_id": "ChIJ3Elm",
                        "text": "3 Elm St, Toronto, ON"
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_NO_HOME_DELIVERY"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.address.suggestions",
        "x-graphql": "platformAppGuestGroupBuyAddressSuggestions",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buy-orders/{token}/confirm-payment": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Confirm a guest group buy card hold",
        "description": "Public: no sign-in token is read. As the signed-in call. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyConfirmPayment",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Confirm a guest group buy card hold",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.orders.confirm-payment",
        "x-graphql": "platformAppGuestGroupBuyConfirmPayment",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buy-orders/{token}": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Get a guest group buy order",
        "description": "Public: no sign-in token is read. As the signed-in call. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyOrder",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a guest group buy order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": "delivered",
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": true
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.orders.show",
        "x-graphql": "platformAppGuestGroupBuyOrder",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buy-orders/{token}/pay": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Resume a guest group buy card hold",
        "description": "Public: no sign-in token is read; the order token is the credential, as for the other guest group buy order calls. As the signed-in call. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyOrderPay",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resume a guest group buy card hold",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "pending",
                      "hold_label": "Waiting for the card",
                      "hold_message": "Complete the card payment to join the group.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": true
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    },
                    "payment": {
                      "client_secret": "pi_3Q_secret_abc",
                      "publishable_key": "pk_live_123",
                      "merchant_country": "CA",
                      "merchant_display_name": "Fresh Market",
                      "capture": "manual"
                    },
                    "reused_intent": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "GROUP_BUY_NOT_AWAITING_HOLD (the hold is no longer pending, or the campaign / group no longer takes orders), or GROUP_BUY_ALREADY_HELD with data.order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "GROUP_BUY_ALREADY_HELD",
                  "message": "The card is already held for this order.",
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "PAYMENT_ERROR (no hold could be started)"
          },
          "404": {
            "description": "GROUP_BUY_ORDER_NOT_FOUND or GROUP_BUY_UNAVAILABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.orders.pay",
        "x-graphql": "platformAppGuestGroupBuyOrderPay",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buy-orders/{token}/received": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Mark a guest group buy order received",
        "description": "Public: no sign-in token is read. As the signed-in call. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyOrderReceived",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The group buy order token (48 letters and digits), returned by the order call.",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mark a guest group buy order received",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "authorized",
                      "hold_label": "Amount held",
                      "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": "delivered",
                      "collected_at": "2026-11-04T12:00:00-05:00",
                      "collected_via": "leader",
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": false
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "GROUP_BUY_NOT_RECEIVABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.orders.received",
        "x-graphql": "platformAppGuestGroupBuyOrderReceived",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buy-orders": {
      "get": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "List a guest's group buy orders",
        "description": "Public: no sign-in token is read. The orders of the tokens the device kept (X-Guest-Order-Token, comma-separated, up to 50), newest first; unknown tokens and other Clients' orders are left out. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyOrders",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": false,
            "description": "The order tokens the device kept, comma-separated (up to 50; GraphQL: order_tokens).",
            "schema": {
              "type": "string",
              "example": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List a guest's group buy orders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                        "number": 1,
                        "campaign": {
                          "code": "FRUITBOX26",
                          "title": "Fruit box",
                          "status": "published",
                          "cutoff_at": "2026-11-07T20:00:00-05:00",
                          "expected_delivery_at": null
                        },
                        "store": {
                          "id": 1,
                          "name": "Fresh Market"
                        },
                        "hold_status": "authorized",
                        "hold_label": "Amount held",
                        "hold_message": "The amount is held on your card. It is charged after orders close at 2026-11-07 20:00 if the group goes ahead, and released otherwise.",
                        "status": "pending_payment",
                        "delivery": "pickup",
                        "units": 2,
                        "total": 11.3,
                        "currency": "CAD",
                        "place": {
                          "name": "Ann's porch",
                          "address": "9 Oak Ave, Toronto, M6G 1A1",
                          "notes": "Evenings",
                          "leader": true
                        },
                        "shipment_status": "delivered",
                        "collected_at": null,
                        "collected_via": null,
                        "created_at": "2026-11-04T12:00:00-05:00",
                        "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                        "actions": {
                          "can_pay": false
                        }
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "per_page": 20,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.orders.index",
        "x-graphql": "platformAppGuestGroupBuyOrders",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buys/{code}/order": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Place a guest group buy order",
        "description": "Public: no sign-in token is read. As the signed-in order, with the verified contact and name (required, max 120): 422 GROUP_BUY_VERIFY_FIRST without a valid contact token, GROUP_BUY_ORDER_REFUSED with errors [name_required] without a name. Keep data.order.token on the device: it is the only way back to the order (no push for guests). Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyPlaceOrder",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "X-Guest-Contact-Token",
            "in": "header",
            "required": true,
            "description": "The contact token from verify/complete (GraphQL: contact_token).",
            "schema": {
              "type": "string",
              "example": "eyJpdiI6Ik1hY0..."
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "lines": {
                  "1": 2
                },
                "receive": "point:1",
                "leader": "ANNPORCH01",
                "address": null,
                "note": "Ring the bell",
                "name": "Gina"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Place a guest group buy order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "token": "Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "number": 1,
                      "campaign": {
                        "code": "FRUITBOX26",
                        "title": "Fruit box",
                        "status": "published",
                        "cutoff_at": "2026-11-07T20:00:00-05:00",
                        "expected_delivery_at": null
                      },
                      "store": {
                        "id": 1,
                        "name": "Fresh Market"
                      },
                      "hold_status": "pending",
                      "hold_label": "Waiting for the card",
                      "hold_message": "The card hold is being confirmed. This page updates by itself.",
                      "status": "pending_payment",
                      "delivery": "pickup",
                      "units": 2,
                      "total": 11.3,
                      "currency": "CAD",
                      "place": {
                        "name": "Ann's porch",
                        "address": "9 Oak Ave, Toronto, M6G 1A1",
                        "notes": "Evenings",
                        "leader": true
                      },
                      "shipment_status": null,
                      "collected_at": null,
                      "collected_via": null,
                      "created_at": "2026-11-04T12:00:00-05:00",
                      "web_url": "https://shop.example.com/portal/group-buy/orders/Q7mVx2LpR9tK4wNc8bHs3dFj6gYz1aEu5iOo0rTy2uWq4ePk",
                      "actions": {
                        "can_pay": true
                      },
                      "subtotal": 10,
                      "delivery_fee": 0,
                      "tax": 1.3,
                      "lines": [
                        {
                          "name": "Apples",
                          "qty": 2,
                          "unit_price": 5,
                          "total": 10
                        }
                      ],
                      "address": {
                        "address_1": "9 Oak Ave",
                        "address_2": null,
                        "city": "Toronto",
                        "province": null,
                        "postcode": "M6G 1A1"
                      },
                      "at_locker": false,
                      "locker": null,
                      "can_confirm_received": false
                    },
                    "payment": {
                      "client_secret": "pi_secret_1",
                      "publishable_key": "pk_test",
                      "merchant_country": "CA",
                      "merchant_display_name": "Fresh Market",
                      "capture": "manual"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "GROUP_BUY_VERIFY_FIRST or GROUP_BUY_ORDER_REFUSED",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "GROUP_BUY_ORDER_REFUSED",
                  "message": "Choose at least one product.",
                  "errors": [
                    "no_items",
                    "address_required"
                  ],
                  "messages": [
                    "Choose at least one product.",
                    "Enter the delivery address and postal code."
                  ]
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.place",
        "x-graphql": "platformAppGuestGroupBuyPlaceOrder",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buys/{code}/quote": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Price a guest group buy order",
        "description": "Public: no sign-in token is read. As the signed-in quote. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). The app answer also carries currency (the Client's currency code the amounts are in), next to the web quote's fields. Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyQuote",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "lines": {
                  "1": 2
                },
                "receive": "home",
                "address": {
                  "address_1": "3 Elm St",
                  "city": "Toronto",
                  "postcode": "M4M 1A1",
                  "delivery_instruction": "Side door"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Price a guest group buy order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "ok": true,
                    "errors": [],
                    "messages": [],
                    "units": 2,
                    "subtotal": 10,
                    "delivery_fee": 0,
                    "tax": 1.3,
                    "total": 11.3,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "404": {
            "description": "GROUP_BUY_UNAVAILABLE or GROUP_BUY_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.quote",
        "x-graphql": "platformAppGuestGroupBuyQuote",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buys/{code}/verify/complete": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Verify a group buy guest's code",
        "description": "Public: no sign-in token is read. Answers contact_token (90 days), sent as X-Guest-Contact-Token when ordering. A contact token from guest/verify/complete of the same app and Client works too. GraphQL names the code argument verification_code. 422 INVALID_VERIFICATION_CODE, INVALID_VERIFICATION_CHALLENGE, VERIFICATION_ATTEMPTS_EXCEEDED. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyVerifyComplete",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "challenge_id": "Qm9vZ2llV29vZ2ll...",
                "code": "123456"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verify a group buy guest's code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "contact_token": "eyJpdiI6Ik1hY0...",
                  "channel": "email",
                  "contact": "g****@example.com",
                  "expires_in": 7776000
                }
              }
            }
          },
          "422": {
            "description": "INVALID_VERIFICATION_CODE"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.verify.complete",
        "x-graphql": "platformAppGuestGroupBuyVerifyComplete",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/group-buys/{code}/verify/request": {
      "post": {
        "tags": [
          "Platform Apps",
          "Group Buy"
        ],
        "summary": "Send a group buy guest a code",
        "description": "Public: no sign-in token is read. Sends a six-digit code to the e-mail address or phone number (the Client's guest verification channel), as guest shipping's verify/request does — the answer is the verification's own body (challenge_id, channel, masked contact, expires_in, resend_after). Group buy verifies guests whether or not the Client offers guest shipping. 422 INVALID_EMAIL / INVALID_PHONE_NUMBER, 429 GUEST_VERIFICATION_RATE_LIMITED, 503 SMS_SERVICE_NOT_CONFIGURED. Available when the calling app's own group_buy capability is on and the Client has a white-label host (404 GROUP_BUY_UNAVAILABLE otherwise), and the campaign's store has group buy on (404 GROUP_BUY_NOT_FOUND). Needs the group_buy capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestGroupBuyVerifyRequest",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The campaign code from the link /group-buy/{code} (10 letters and digits).",
            "schema": {
              "type": "string",
              "example": "FRUITBOX26"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "contact": "gina@example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Send a group buy guest a code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "A verification code was sent.",
                  "challenge_id": "Qm9vZ2llV29vZ2llQm9vZ2llV29vZ2llQm9vZ2llV29vZ2llQm9vZ2llV29vZ2ll",
                  "channel": "email",
                  "contact": "g****@example.com",
                  "expires_in": 600,
                  "resend_after": 60
                }
              }
            }
          },
          "422": {
            "description": "INVALID_EMAIL or INVALID_PHONE_NUMBER"
          },
          "429": {
            "description": "GUEST_VERIFICATION_RATE_LIMITED"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry group_buy"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.group-buy.verify.request",
        "x-graphql": "platformAppGuestGroupBuyVerifyRequest",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "group_buy"
      }
    },
    "/app/v1/clients/{clientCode}/guest/shipments/{guestOrderId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get a guest shipment",
        "description": "Public; with X-Guest-Order-Token or an X-Guest-Contact-Token of the same contact (90 days). status is pending_payment, paid, placing, placed, expired, cancelled, refunded or refund_required. While unpaid, pay_url and pay_before; once placed, order carries the order's reference, status_group and status_label, the two addresses, packages with tracking numbers and, for a label, label.carrier_name and carrier_tracking_numbers. Needs the guest.shipping capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestShipment",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "guestOrderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 42
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": false,
            "description": "The order token returned once by POST .../guest/shipments. Either this or X-Guest-Contact-Token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Guest-Contact-Token",
            "in": "header",
            "required": false,
            "description": "Contact token from verify/complete.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The guest shipment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestOrderAnswer"
                },
                "example": {
                  "result": true,
                  "guest_order": {
                    "id": 42,
                    "kind": "self_delivery",
                    "status": "placed",
                    "amount": "12.40",
                    "currency": "CAD",
                    "contact": "g****@example.com",
                    "created_at": "2026-10-09T10:00:00-04:00",
                    "pay_url": null,
                    "pay_before": null,
                    "can_cancel": false,
                    "order": {
                      "type": "self_delivery",
                      "ref": "SR41000123",
                      "status_group": "active",
                      "status_label": "Out for delivery",
                      "packages": [
                        {
                          "tracking_number": "SR41000123-1"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "GUEST_ORDER_NOT_FOUND, or APP_CONTEXT_NOT_FOUND"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry guest.shipping"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.shipments.show",
        "x-graphql": "platformAppGuestShipment",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "guest.shipping"
      }
    },
    "/app/v1/clients/{clientCode}/guest/shipments/{guestOrderId}/cancel": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Cancel a guest shipment",
        "description": "Public; with X-Guest-Order-Token or an X-Guest-Contact-Token of the same contact. An unpaid shipment is withdrawn and its payment page closes. A created one is cancelled while its order still can be (no pickup yet, label not used; can_cancel tells): the order is cancelled, its charge returned to the Client's attribution customer, the guest refunded in full and told by email or SMS; when the gateway cannot refund on its own the status is refund_required. Needs the guest.shipping capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestShipmentCancel",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "guestOrderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 42
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": false,
            "description": "The order token returned once by POST .../guest/shipments. Either this or X-Guest-Contact-Token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Guest-Contact-Token",
            "in": "header",
            "required": false,
            "description": "Contact token from verify/complete.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Withdrawn",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestOrderAnswer"
                },
                "example": {
                  "result": true,
                  "guest_order": {
                    "id": 42,
                    "kind": "self_delivery",
                    "status": "cancelled",
                    "amount": "12.40",
                    "currency": "CAD",
                    "contact": "g****@example.com",
                    "created_at": "2026-10-09T10:00:00-04:00",
                    "pay_url": null,
                    "pay_before": null,
                    "can_cancel": false,
                    "order": null
                  }
                }
              }
            }
          },
          "404": {
            "description": "GUEST_ORDER_NOT_FOUND, or APP_CONTEXT_NOT_FOUND"
          },
          "409": {
            "description": "GUEST_ORDER_NOT_CANCELLABLE: being paid, being created, or the order can no longer be cancelled"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry guest.shipping"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.shipments.cancel",
        "x-graphql": "platformAppGuestShipmentCancel",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "guest.shipping"
      }
    },
    "/app/v1/clients/{clientCode}/guest/shipments/{guestOrderId}/label": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get the label of a guest shipment",
        "description": "Public; with X-Guest-Order-Token or an X-Guest-Contact-Token of the same contact. The label PDF of a placed label shipment, base64 in pdf_data. Needs the guest.shipping capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestShipmentLabel",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "guestOrderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 42
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": false,
            "description": "The order token returned once by POST .../guest/shipments. Either this or X-Guest-Contact-Token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Guest-Contact-Token",
            "in": "header",
            "required": false,
            "description": "Contact token from verify/complete.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The label",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestLabel"
                },
                "example": {
                  "result": true,
                  "format": "pdf",
                  "tracking_numbers": [
                    "1Z999AA10123456784"
                  ],
                  "pdf_data": "JVBERi0xLjQKJ..."
                }
              }
            }
          },
          "404": {
            "description": "GUEST_ORDER_NOT_FOUND for any other shipment, or APP_CONTEXT_NOT_FOUND"
          },
          "409": {
            "description": "LABEL_NOT_AVAILABLE: the carrier has not produced it yet"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry guest.shipping"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.shipments.label",
        "x-graphql": "platformAppGuestShipmentLabel",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "guest.shipping"
      }
    },
    "/app/v1/clients/{clientCode}/guest/shipments/rate": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Price a guest shipment",
        "description": "Public. Prices a local delivery and carrier labels for a guest of a Client that offers guest shipping (capability guest.shipping), as the Client's attribution customer: its price plan, label accounts and service switches. The body is the shipment (from_* and to_* name, telephone, address, city, province, postcode, country; packages; signature_option); any other field, such as a customer or a channel, is ignored. Each rate_id is a guest quote: valid for this Client and this exact shipment only, for 30 minutes. A self delivery rate without a price is reported in errors with code NOT_PRICED: a guest pays before the order exists. Carrier quotes: six per minute per caller and Client. Needs the guest.shipping capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestShipmentRate",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "from_name": "Ann Lee",
                "from_telephone": "+14165550100",
                "from_address": "1 King St W",
                "from_city": "Toronto",
                "from_province": "ON",
                "from_postcode": "M5H 1A1",
                "from_country": "CA",
                "to_name": "Bo Chen",
                "to_telephone": "+14165550101",
                "to_address": "300 Front St W",
                "to_city": "Toronto",
                "to_province": "ON",
                "to_postcode": "M5V 2T6",
                "to_country": "CA",
                "packages": [
                  {
                    "weight": 2,
                    "length": 30,
                    "width": 20,
                    "height": 10,
                    "weight_unit": 1,
                    "dimension_unit": 1
                  }
                ],
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rates, as POST /v1/uniorder/rate, with guest rate ids",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestRates"
                },
                "example": {
                  "result": true,
                  "rates": [
                    {
                      "rate_id": "eyJpdiI6Ikd1ZXN0UXVvdGUi...",
                      "type": "self_delivery",
                      "shipping_price": "12.40",
                      "currency": "CAD"
                    },
                    {
                      "rate_id": "eyJpdiI6Ikd1ZXN0TGFiZWwi...",
                      "type": "label_service",
                      "shipping_price": "20.00",
                      "currency": "CAD",
                      "carrier_name": "UPS",
                      "service_name": "Ground",
                      "transit_days": 2
                    }
                  ],
                  "errors": []
                }
              }
            }
          },
          "400": {
            "description": "Invalid shipment: result false with message"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry guest.shipping"
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: the Client does not offer guest shipping in this app"
          },
          "429": {
            "description": "TOO_MANY_REQUESTS: carrier quote limit"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.shipments.rate",
        "x-graphql": "platformAppGuestShipmentRate",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "guest.shipping"
      }
    },
    "/app/v1/clients/{clientCode}/guest/shipments": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Submit a guest shipment for payment",
        "description": "Public; needs X-Guest-Contact-Token. The body is the rated shipment, exactly as rated, with rate_id from POST .../guest/shipments/rate, and optionally note and need_pick_up (self delivery). Nothing is created yet: the shipment waits for its payment on the shared payment page (pay_url, gateways only, no wallet) until pay_before. Once paid, the payment is credited to the Client's attribution customer and the order is created through uniorder (local delivery dispatched, label bought); if that fails the payment is refunded. The guest receives the outcome by email or SMS on the verified contact; the link in it carries no token. order_token is shown once and opens this shipment later. Needs the guest.shipping capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestShipmentSubmit",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "X-Guest-Contact-Token",
            "in": "header",
            "required": true,
            "description": "Contact token from verify/complete.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "quote_token": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Optional. The token of the public quote this shipment comes from. Recorded on the quote once the paid shipment is created; an unknown or already converted token is ignored."
                  }
                },
                "additionalProperties": true
              },
              "example": {
                "from_name": "Ann Lee",
                "from_telephone": "+14165550100",
                "from_address": "1 King St W",
                "from_city": "Toronto",
                "from_province": "ON",
                "from_postcode": "M5H 1A1",
                "from_country": "CA",
                "to_name": "Bo Chen",
                "to_telephone": "+14165550101",
                "to_address": "300 Front St W",
                "to_city": "Toronto",
                "to_province": "ON",
                "to_postcode": "M5V 2T6",
                "to_country": "CA",
                "packages": [
                  {
                    "weight": 2,
                    "length": 30,
                    "width": 20,
                    "height": 10,
                    "weight_unit": 1,
                    "dimension_unit": 1
                  }
                ],
                "rate_id": "eyJpdiI6Ikd1ZXN0UXVvdGUi...",
                "note": "Back door",
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Waiting for payment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestOrderCreated"
                },
                "example": {
                  "result": true,
                  "order_token": "k3J9xQ2mV8pL5tR1wZ7cN4bH6dF0gS2aY9eU3iO8",
                  "guest_order": {
                    "id": 42,
                    "kind": "self_delivery",
                    "status": "pending_payment",
                    "amount": "12.40",
                    "currency": "CAD",
                    "contact": "g****@example.com",
                    "created_at": "2026-10-09T10:00:00-04:00",
                    "pay_url": "https://ship.example.com/pay/r/3f9c0d6a1b2e4f5a6b7c8d9e0f1a2b3c",
                    "pay_before": "2026-10-09T10:30:00-04:00",
                    "can_cancel": true,
                    "order": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: the Client does not offer guest shipping in this app"
          },
          "422": {
            "description": "RATE_ID_INVALID: expired, another Client, or a different shipment"
          },
          "429": {
            "description": "GUEST_ORDER_LIMIT: per contact per day, per IP address per hour"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry guest.shipping"
          }
        },
        "x-route-name": "openapp.guest.shipments.submit",
        "x-graphql": "platformAppGuestShipmentSubmit",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "guest.shipping"
      },
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List a verified contact's guest shipments",
        "description": "Public; needs X-Guest-Contact-Token. The guest shipments of that contact at this Client from the last 90 days, newest first, at most 50: for a guest on a new device. Needs the guest.shipping capability on the token; answered exactly as the internal route.",
        "operationId": "platformAppGuestShipments",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "X-Guest-Contact-Token",
            "in": "header",
            "required": true,
            "description": "Contact token from verify/complete.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Guest shipments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestOrderList"
                },
                "example": {
                  "result": true,
                  "items": [
                    {
                      "id": 42,
                      "kind": "self_delivery",
                      "status": "pending_payment",
                      "amount": "12.40",
                      "currency": "CAD",
                      "contact": "g****@example.com",
                      "created_at": "2026-10-09T10:00:00-04:00",
                      "pay_url": "https://ship.example.com/pay/r/3f9c0d6a1b2e4f5a6b7c8d9e0f1a2b3c",
                      "pay_before": "2026-10-09T10:30:00-04:00",
                      "can_cancel": true,
                      "order": null
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: the Client does not offer guest shipping in this app"
          },
          "403": {
            "description": "insufficient_scope: the token does not carry guest.shipping"
          }
        },
        "x-route-name": "openapp.guest.shipments.index",
        "x-graphql": "platformAppGuestShipments",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "x-capability": "guest.shipping"
      }
    },
    "/app/v1/clients/{clientCode}/guest/storefront": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Storefront entry (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). Which home cards the app shows (A3, A4): `mall` (null when the platform gave the client no mall or the client has no marketplace) with `operations_enabled` (false = the mall is its store directory only), `stores_available` (listed stores exist), `group_buy_available` (the app's group_buy capability is on and a group buy can be ordered now). Never 404 for a known client: a client without the marketplace answers all off. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStorefront",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "mall": {
                      "enabled": true,
                      "operations_enabled": true,
                      "name": "Client",
                      "web_url": "https://shop.example.com/mall"
                    },
                    "stores_available": true,
                    "group_buy_available": true,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.storefront",
        "x-graphql": "platformAppGuestStorefront",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store page (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). A listed store of the client (also one that is not in the mall): profile, whether it takes orders now (`accepting_orders`, `intake_blockers`), the order types it can take with ASAP and the time slots (store clock, `timezone`), categories, the menu as `sections` (category order; products of no active category last, `label` null) with each item's price, stock state and option groups (each group and value with `image_url`, null without an image), the featured row and banners (unfiltered view only), its group buys and the 10 newest approved reviews. `q`, `cat` (with its sub-categories) and `sort` filter the menu like the web. `table` enters the dine-in context: `dine_in.table_code` is set and only dine_in is offered; an unknown table, or a store without dine-in, answers 404 TABLE_NOT_FOUND. Without `table`, dine_in is never listed. Every product card carries currency: the currency code its prices are in (the store's Client's). Added (docs/STORE-STYLES-DESIGN.md P2): design {style simple|multi_page — the style this answer is drawn in (a table always gets simple), published_version (0 = never published; the store then looks as before), nav_categories[{id, name}], top_blocks — in the simple style, the blocks above the menu on the unfiltered view of a store that published a design; banners, announcement and featured stay in the answer as before}. In the multi-page style the app opens /home, /categories/{categoryId} and the product page's page_blocks. Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStore",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Words in the item name"
          },
          {
            "name": "cat",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Store category id"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "price_asc",
                "price_desc",
                "name",
                "newest"
              ]
            }
          },
          {
            "name": "table",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "T12"
            },
            "description": "Table code from the table QR (/s/{slug}/t/{table})"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place",
                      "description": "",
                      "store_type": "restaurant",
                      "store_type_label": "Restaurant",
                      "tags": [
                        "pizza",
                        "halal"
                      ],
                      "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                      "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                      "rating_avg": 4.6,
                      "rating_count": 38,
                      "address": "12 King St W",
                      "city": "Toronto",
                      "phone": "",
                      "min_order_amount": 15,
                      "prep_time_minutes": 20,
                      "timezone": "America/Toronto",
                      "announcement": "",
                      "social_links": {
                        "instagram": "https://instagram.com/pizzaplace"
                      },
                      "food": true,
                      "guest_orders": true,
                      "currency": "CAD",
                      "web_url": "https://shop.example.com/s/pizza-place-1"
                    },
                    "accepting_orders": true,
                    "intake_blockers": [],
                    "order_types": [
                      {
                        "type": "collection",
                        "label": "Pick-up",
                        "accepting": true,
                        "asap": true,
                        "days": [
                          {
                            "date": "2026-10-14",
                            "slots": [
                              "15:30",
                              "15:45",
                              "16:00"
                            ]
                          }
                        ]
                      }
                    ],
                    "dine_in": null,
                    "banners": [
                      {
                        "image_url": "https://shop.example.com/storage/stores/31/banner.jpg",
                        "link": "https://shop.example.com/s/pizza-place-1/i/1"
                      }
                    ],
                    "categories": [
                      {
                        "id": 1,
                        "parent_id": null,
                        "name": "Pizzas"
                      }
                    ],
                    "sections": [
                      {
                        "category_id": 1,
                        "label": "Pizzas",
                        "items": [
                          {
                            "id": 1,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Margherita",
                            "description": "Tomato, mozzarella, basil",
                            "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                            "price": 12,
                            "list_price": 14,
                            "compare_at_price": 14,
                            "on_sale": true,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [
                              {
                                "code": "gluten",
                                "label": "Gluten"
                              },
                              {
                                "code": "milk",
                                "label": "Milk"
                              }
                            ],
                            "affiliate": false,
                            "external_url": null,
                            "option_groups": [
                              {
                                "id": 1,
                                "label": "Size",
                                "type": "radio",
                                "required": true,
                                "min": 0,
                                "max": null,
                                "image_url": null,
                                "values": [
                                  {
                                    "id": 1,
                                    "label": "12 inch",
                                    "delta": 0,
                                    "default": false,
                                    "image_url": null
                                  },
                                  {
                                    "id": 2,
                                    "label": "16 inch",
                                    "delta": 4,
                                    "default": false,
                                    "image_url": null
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "category_id": null,
                        "label": null,
                        "items": [
                          {
                            "id": 2,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Cola",
                            "description": "",
                            "image_url": null,
                            "price": 2.5,
                            "list_price": 2.5,
                            "compare_at_price": null,
                            "on_sale": false,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [],
                            "affiliate": false,
                            "external_url": null,
                            "option_groups": []
                          }
                        ]
                      }
                    ],
                    "featured": [
                      {
                        "id": 1,
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "name": "Margherita",
                        "description": "Tomato, mozzarella, basil",
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                        "price": 12,
                        "list_price": 14,
                        "compare_at_price": 14,
                        "on_sale": true,
                        "currency": "CAD",
                        "available": true,
                        "within_mealtimes": true,
                        "mealtimes": [],
                        "allergens": [
                          {
                            "code": "gluten",
                            "label": "Gluten"
                          },
                          {
                            "code": "milk",
                            "label": "Milk"
                          }
                        ],
                        "affiliate": false,
                        "external_url": null,
                        "option_groups": [
                          {
                            "id": 1,
                            "label": "Size",
                            "type": "radio",
                            "required": true,
                            "min": 0,
                            "max": null,
                            "image_url": null,
                            "values": [
                              {
                                "id": 1,
                                "label": "12 inch",
                                "delta": 0,
                                "default": false,
                                "image_url": null
                              },
                              {
                                "id": 2,
                                "label": "16 inch",
                                "delta": 4,
                                "default": false,
                                "image_url": null
                              }
                            ]
                          }
                        ]
                      }
                    ],
                    "group_buys": [
                      {
                        "code": "PZBOX7",
                        "title": "Friday pizza box",
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "opens_at": "2026-10-14T14:00:00-04:00",
                        "cutoff_at": "2026-10-16T15:00:00-04:00",
                        "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                      }
                    ],
                    "reviews": [
                      {
                        "rating": 5,
                        "comment": "Great crust",
                        "reviewer": null,
                        "merchant_reply": "Thank you!",
                        "created_at": "2026-10-14T15:00:00-04:00"
                      }
                    ],
                    "filters": {
                      "q": "",
                      "sort": "",
                      "cat": 0
                    },
                    "design": {
                      "style": "simple",
                      "published_version": 2,
                      "nav_categories": [
                        {
                          "id": 5,
                          "name": "Kitchen"
                        }
                      ],
                      "top_blocks": [
                        {
                          "id": "b9a8b7c6d5",
                          "type": "announcement",
                          "settings": {
                            "tone": "accent"
                          },
                          "data": {
                            "text": "Closed on Monday"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.show",
        "x-graphql": "platformAppGuestStore",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/home": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store home page (multi-page style) (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). The home page of a store in the multi-page style (docs/STORE-STYLES-DESIGN.md P2): the store card, accepting_orders, design {style, published_version, nav_categories[{id, name}] — the top-level categories for the category bar} and blocks in the order the merchant published. A store in the simple style answers 404 STORE_PAGE_NOT_FOUND (its home is the store page); an unknown store 404 STORE_NOT_FOUND. Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreHome",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "home-goods-1"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "home-goods-1",
                      "name": "Home Goods",
                      "description": "",
                      "store_type": "retail",
                      "store_type_label": "Retail Store",
                      "tags": [],
                      "logo_url": null,
                      "cover_url": null,
                      "rating_avg": 0,
                      "rating_count": 0,
                      "address": "1 Main St",
                      "city": "Toronto",
                      "currency": "CAD",
                      "web_url": "https://shop.example.com/s/home-goods-1"
                    },
                    "accepting_orders": true,
                    "design": {
                      "style": "multi_page",
                      "published_version": 3,
                      "nav_categories": [
                        {
                          "id": 5,
                          "name": "Kitchen"
                        },
                        {
                          "id": 7,
                          "name": "Garden"
                        }
                      ]
                    },
                    "blocks": [
                      {
                        "id": "b1a2b3c4d5",
                        "type": "banner",
                        "settings": {
                          "height": "medium",
                          "autoplay": true
                        },
                        "data": {
                          "slides": [
                            {
                              "image_url": "https://shop.example.com/storage/merchant_stores/1/banner_1.jpg",
                              "link": "https://shop.example.com/s/home-goods-1/c/5"
                            }
                          ]
                        }
                      },
                      {
                        "id": "b2b3c4d5e6",
                        "type": "category_entry",
                        "settings": {
                          "columns": 4,
                          "display": "image"
                        },
                        "data": {
                          "title": "Categories",
                          "categories": [
                            {
                              "id": 5,
                              "name": "Kitchen",
                              "image_url": null
                            },
                            {
                              "id": 7,
                              "name": "Garden",
                              "image_url": null
                            }
                          ]
                        }
                      },
                      {
                        "id": "b3c4d5e6f7",
                        "type": "product_grid",
                        "settings": {
                          "limit": 8,
                          "columns": 4,
                          "layout": "grid"
                        },
                        "data": {
                          "title": "New arrivals",
                          "products": [
                            {
                              "id": 12,
                              "store": {
                                "id": 1,
                                "slug": "home-goods-1",
                                "name": "Home Goods"
                              },
                              "name": "Copper pan",
                              "description": "",
                              "image_url": "https://shop.example.com/storage/products/12/pan.jpg",
                              "price": 40,
                              "list_price": 40,
                              "compare_at_price": null,
                              "on_sale": false,
                              "currency": "CAD",
                              "available": true,
                              "within_mealtimes": true,
                              "mealtimes": [],
                              "allergens": [],
                              "affiliate": false,
                              "external_url": null
                            }
                          ]
                        }
                      },
                      {
                        "id": "b4d5e6f7a8",
                        "type": "image_text",
                        "settings": {
                          "image_position": "left"
                        },
                        "data": {
                          "image_url": "https://shop.example.com/storage/merchant_stores/1/banner_2.jpg",
                          "title": "Our story",
                          "body": "Made by hand since 1990",
                          "link": "",
                          "button_text": ""
                        }
                      },
                      {
                        "id": "b5e6f7a8b9",
                        "type": "video",
                        "settings": {
                          "autoplay": false
                        },
                        "data": {
                          "title": "",
                          "kind": "embed",
                          "url": "https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_PAGE_NOT_FOUND",
                  "message": "This store does not use the multi-page style."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.home",
        "x-graphql": "platformAppGuestStoreHome",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/categories/{categoryId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store category page (multi-page style) (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). A category page of a store in the multi-page style (docs/STORE-STYLES-DESIGN.md P2): store, category {id, parent_id, name}, accepting_orders, design (as the home page) and blocks — the category's own layout when it has one, else the store's; the product_list block holds the category's items and its sub-categories', paged and filtered by sort (price_asc, price_desc, name, newest), sub (a direct sub-category), in_stock and page. 404 STORE_PAGE_NOT_FOUND in the simple style, CATEGORY_NOT_FOUND for a category the store does not have (or has switched off). Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreCategory",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "home-goods-1"
            }
          },
          {
            "name": "categoryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 5
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "price_asc",
                "price_desc",
                "name",
                "newest"
              ]
            }
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "A direct sub-category id"
          },
          {
            "name": "in_stock",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "home-goods-1",
                      "name": "Home Goods"
                    },
                    "category": {
                      "id": 5,
                      "parent_id": null,
                      "name": "Kitchen"
                    },
                    "accepting_orders": true,
                    "design": {
                      "style": "multi_page",
                      "published_version": 3,
                      "nav_categories": [
                        {
                          "id": 5,
                          "name": "Kitchen"
                        },
                        {
                          "id": 7,
                          "name": "Garden"
                        }
                      ]
                    },
                    "blocks": [
                      {
                        "id": "c1d2e3f4a5",
                        "type": "category_header",
                        "settings": {
                          "show_image": true,
                          "show_description": true
                        },
                        "data": {
                          "name": "Kitchen",
                          "image_url": null,
                          "description": "Pots, pans and knives"
                        }
                      },
                      {
                        "id": "c2d3e4f5a6",
                        "type": "product_list",
                        "settings": {
                          "page_size": 24,
                          "columns": 4,
                          "show_filters": true
                        },
                        "data": {
                          "items": [
                            {
                              "id": 12,
                              "store": {
                                "id": 1,
                                "slug": "home-goods-1",
                                "name": "Home Goods"
                              },
                              "name": "Copper pan",
                              "description": "",
                              "image_url": "https://shop.example.com/storage/products/12/pan.jpg",
                              "price": 40,
                              "list_price": 40,
                              "compare_at_price": null,
                              "on_sale": false,
                              "currency": "CAD",
                              "available": true,
                              "within_mealtimes": true,
                              "mealtimes": [],
                              "allergens": [],
                              "affiliate": false,
                              "external_url": null
                            }
                          ],
                          "pagination": {
                            "current_page": 1,
                            "last_page": 1,
                            "per_page": 24,
                            "total": 1,
                            "has_more": false
                          },
                          "subcategories": [
                            {
                              "id": 6,
                              "name": "Knives"
                            }
                          ],
                          "filters": {
                            "q": "",
                            "sort": "",
                            "sub": 0,
                            "in_stock": false
                          }
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_PAGE_NOT_FOUND",
                  "message": "This store does not use the multi-page style."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.category",
        "x-graphql": "platformAppGuestStoreCategory",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/products/{productId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Product page (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). One product on sale in the store: the card fields plus `sku`, all `images`, active `variants` with their storefront price, `option_groups` (each group and value with `image_url`, null without an image), `group_buy` (lowest group price while an orderable campaign carries it, else null), the 20 newest approved reviews and up to 6 related products of the same category. Every product card carries currency: the currency code its prices are in (the store's Client's). Added (docs/STORE-STYLES-DESIGN.md P2): page_blocks — in the multi-page style, the product page's blocks in order (the product's own layout, else the store's; buy_box marks where this answer's purchase area goes); null in the simple style. Each block is {id, type, settings, data}. type is one of banner, announcement, category_entry, product_grid, image_text, video, coupons, group_buys, reviews, category_header, product_list (category pages), buy_box, details, specs, product_reviews, related (product pages). settings holds only how the block is drawn (columns, layout, height, tone, display, image_position, autoplay, page_size, show_*); data holds what it shows, resolved in the answer language with absolute URLs: banner {slides[{image_url, link}]}, announcement {text}, category_entry {title, categories[{id, name, image_url}]}, product_grid and related {title, products[product card]}, image_text {image_url, title, body, link, button_text}, video {title, kind embed|file, url}, coupons {title, coupons[{id, name, description, code, ends_on}]}, group_buys {title, group_buys[]}, reviews {title, reviews[{rating, comment, reviewer, merchant_reply, created_at}]}, category_header {name, image_url, description}, product_list {items[product card], pagination, subcategories[{id, name}], filters{q, sort, sub, in_stock}}, details {title, body, image_urls[]}, specs {title, fields[{label, value}]}, product_reviews {title, reviews[{rating, comment, created_at}]}, buy_box {} (the product answer itself). A block with nothing to show is left out; unknown types should be skipped. Added: share — how the store lets buyers share this product, null while it offers none: {url (the product's web page, on the client's white-label host when it has one), title, channels (the store's choice in display order, each one of system, wechat, whatsapp, facebook, x, telegram, line, linkedin, reddit, pinterest, threads, tumblr, viber, weibo, qq, sms, email, copy, qr; system = the phone's own share menu, wechat = WeChat, which has no share address: copy the url and open WeChat (weixin://) on a phone, show the url as a QR code to scan with WeChat elsewhere, copy = copy the url, qr = show the url as a QR code), links (channel => address to open, for the chosen network, sms and email channels)}. Skip a channel the app does not know. Show only the listed channels. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreProduct",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Added (docs/SKU-STRUCTURES-DESIGN.md SX3, SX11): custom_fields [{key, label, value}] — the merchant's custom SKU fields shown to buyers that hold a value, labelled in the request's language (an option shows its label in that language when it has one) — only when there is one; otherwise the answer is as before. Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 1,
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "name": "Margherita",
                    "description": "Tomato, mozzarella, basil",
                    "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                    "price": 12,
                    "list_price": 14,
                    "compare_at_price": 14,
                    "on_sale": true,
                    "currency": "CAD",
                    "available": true,
                    "within_mealtimes": true,
                    "mealtimes": [],
                    "allergens": [
                      {
                        "code": "gluten",
                        "label": "Gluten"
                      },
                      {
                        "code": "milk",
                        "label": "Milk"
                      }
                    ],
                    "affiliate": false,
                    "external_url": null,
                    "option_groups": [
                      {
                        "id": 1,
                        "label": "Size",
                        "type": "radio",
                        "required": true,
                        "min": 0,
                        "max": null,
                        "image_url": null,
                        "values": [
                          {
                            "id": 1,
                            "label": "12 inch",
                            "delta": 0,
                            "default": false,
                            "image_url": null
                          },
                          {
                            "id": 2,
                            "label": "16 inch",
                            "delta": 4,
                            "default": false,
                            "image_url": null
                          }
                        ]
                      }
                    ],
                    "sku": "MARGHERITA",
                    "images": [
                      "https://shop.example.com/storage/products/88/margherita.jpg"
                    ],
                    "variants": [],
                    "accepting_orders": true,
                    "group_buy": {
                      "price": 10.5,
                      "code": "PZBOX7",
                      "title": "Friday pizza box",
                      "cutoff_at": "2026-10-16T15:00:00-04:00",
                      "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                    },
                    "reviews": [
                      {
                        "rating": 5,
                        "comment": "Best in town",
                        "created_at": "2026-10-14T15:00:00-04:00"
                      }
                    ],
                    "related": [],
                    "share": {
                      "url": "https://shop.example.com/s/pizza-place-1/i/1",
                      "title": "Margherita",
                      "channels": [
                        "system",
                        "whatsapp",
                        "facebook",
                        "copy",
                        "qr"
                      ],
                      "links": {
                        "whatsapp": "https://wa.me/?text=Margherita%20https%3A%2F%2Fshop.example.com%2Fs%2Fpizza-place-1%2Fi%2F1",
                        "facebook": "https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fshop.example.com%2Fs%2Fpizza-place-1%2Fi%2F1"
                      }
                    },
                    "page_blocks": [
                      {
                        "id": "p1a2b3c4d5",
                        "type": "buy_box",
                        "settings": {
                          "show_thumbnails": true
                        },
                        "data": {}
                      },
                      {
                        "id": "p2b3c4d5e6",
                        "type": "details",
                        "settings": {},
                        "data": {
                          "title": "Details",
                          "body": "Heavy copper pan",
                          "image_urls": []
                        }
                      },
                      {
                        "id": "p3c4d5e6f7",
                        "type": "related",
                        "settings": {
                          "limit": 6
                        },
                        "data": {
                          "title": "Related products",
                          "products": [
                            {
                              "id": 12,
                              "store": {
                                "id": 1,
                                "slug": "home-goods-1",
                                "name": "Home Goods"
                              },
                              "name": "Copper pan",
                              "description": "",
                              "image_url": "https://shop.example.com/storage/products/12/pan.jpg",
                              "price": 40,
                              "list_price": 40,
                              "compare_at_price": null,
                              "on_sale": false,
                              "currency": "CAD",
                              "available": true,
                              "within_mealtimes": true,
                              "mealtimes": [],
                              "allergens": [],
                              "affiliate": false,
                              "external_url": null
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.product",
        "x-graphql": "platformAppGuestStoreProduct",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/cart": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Cart of one store (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). The buyer's cart in this store (empty when there is none). Signed in: the linked identity's cart — the same cart as on the web — or, for an account without a linked identity, the account's own cart. Guest: the cart of X-Guest-Cart-Token; `guest_cart_token` echoes the token in use (null without one). Line prices are display prices; checkout prices again. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreCart",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "X-Guest-Cart-Token",
            "in": "header",
            "required": false,
            "description": "Guest only: the guest cart token from an earlier cart answer (40 letters and digits). Absent or in another shape: no cart; a cart write then issues a new token.",
            "schema": {
              "type": "string",
              "example": "3gldEoWgIUaixQRT2beBfqX7kg0CKDZtSrRXeeuj"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD",
                    "guest_cart_token": "3gldEoWgIUaixQRT2beBfqX7kg0CKDZtSrRXeeuj"
                  }
                }
              }
            },
            "headers": {
              "X-Guest-Cart-Token": {
                "description": "The guest cart token in use (set when there is one).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.cart",
        "x-graphql": "platformAppGuestStoreCart",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/cart/items": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Add to cart (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). Put a product in the cart with the web rules: the store takes orders now (only dine-in when `table` names a table), the product is on sale, in stock and inside its mealtimes, a product with variants names its `product_variant_id`, and `options` keep the item's option rules ({product_options.id: [store_option_value_id, ...]}, the ids from option_groups[].id and values[].id). An identical line (product, variant, options) grows. A guest's first write issues the guest cart token: keep it (body `guest_cart_token` and response header X-Guest-Cart-Token) and send it with every later cart call. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreCartAdd",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "X-Guest-Cart-Token",
            "in": "header",
            "required": false,
            "description": "Guest only: the guest cart token from an earlier cart answer (40 letters and digits). Absent or in another shape: no cart; a cart write then issues a new token.",
            "schema": {
              "type": "string",
              "example": "3gldEoWgIUaixQRT2beBfqX7kg0CKDZtSrRXeeuj"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product_id",
                  "qty"
                ],
                "properties": {
                  "product_id": {
                    "type": "integer",
                    "example": 1
                  },
                  "product_variant_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "qty": {
                    "type": "integer",
                    "minimum": 1,
                    "example": 2
                  },
                  "options": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      }
                    },
                    "example": {
                      "1": [
                        2
                      ]
                    }
                  },
                  "table": {
                    "type": "string",
                    "example": "T12"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD",
                    "guest_cart_token": "3gldEoWgIUaixQRT2beBfqX7kg0CKDZtSrRXeeuj"
                  }
                }
              }
            },
            "headers": {
              "X-Guest-Cart-Token": {
                "description": "The guest cart token in use (set when there is one).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "422": {
            "description": "VALIDATION_FAILED (with errors) | STORE_CLOSED | ITEM_UNAVAILABLE (a guest answer carries guest_cart_token)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.cart.add",
        "x-graphql": "platformAppGuestStoreCartAdd",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/cart/items/{itemId}": {
      "patch": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Change a cart line quantity (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). Set the quantity of one line (items[].id); 0 removes it. A line that is not in this buyer's cart changes nothing and the cart is answered. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreCartUpdate",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "X-Guest-Cart-Token",
            "in": "header",
            "required": false,
            "description": "Guest only: the guest cart token from an earlier cart answer (40 letters and digits). Absent or in another shape: no cart; a cart write then issues a new token.",
            "schema": {
              "type": "string",
              "example": "3gldEoWgIUaixQRT2beBfqX7kg0CKDZtSrRXeeuj"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "qty"
                ],
                "properties": {
                  "qty": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD"
                  }
                }
              }
            },
            "headers": {
              "X-Guest-Cart-Token": {
                "description": "The guest cart token in use (set when there is one).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "422": {
            "description": "VALIDATION_FAILED"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.cart.update",
        "x-graphql": "platformAppGuestStoreCartUpdate",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Remove a cart line (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). Remove one line (items[].id). A line that is not in this buyer's cart changes nothing and the cart is answered. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreCartRemove",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "pizza-place-1"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "X-Guest-Cart-Token",
            "in": "header",
            "required": false,
            "description": "Guest only: the guest cart token from an earlier cart answer (40 letters and digits). Absent or in another shape: no cart; a cart write then issues a new token.",
            "schema": {
              "type": "string",
              "example": "3gldEoWgIUaixQRT2beBfqX7kg0CKDZtSrRXeeuj"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "store": {
                      "id": 1,
                      "slug": "pizza-place-1",
                      "name": "Pizza Place"
                    },
                    "items": [
                      {
                        "id": 1,
                        "product_id": 1,
                        "product_variant_id": null,
                        "name": "Margherita",
                        "options_label": "16 inch",
                        "qty": 2,
                        "unit_price": 16,
                        "total": 32,
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg"
                      }
                    ],
                    "subtotal": 32,
                    "count": 2,
                    "currency": "CAD"
                  }
                }
              }
            },
            "headers": {
              "X-Guest-Cart-Token": {
                "description": "The guest cart token in use (set when there is one).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.stores.cart.remove",
        "x-graphql": "platformAppGuestStoreCartRemove",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/checkout/quote": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Price a guest's cart at a store",
        "description": "Price a guest's cart at a store; login_required says whether the store takes guest orders. Guests: X-Guest-Cart-Token names the cart. table_code puts the order at that table (dine-in only). Errors: 404 STORE_NOT_FOUND, 422 CART_EMPTY, 422 TABLE_NOT_FOUND, 422 VALIDATION_FAILED. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreCheckoutQuote",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "bistro"
            }
          },
          {
            "name": "X-Guest-Cart-Token",
            "in": "header",
            "required": false,
            "description": "The guest's cart token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "ok": true,
                    "errors": [],
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "min_order": 0.0,
                    "total": 29.0,
                    "tax": 0.0,
                    "price_changed": false,
                    "currency": "CAD",
                    "order_type": "delivery",
                    "table_code": null,
                    "order_types": [
                      "delivery",
                      "collection",
                      "dine_in"
                    ],
                    "payment_methods": [
                      "stripe"
                    ],
                    "slots": {
                      "delivery": {
                        "asap": true,
                        "days": [
                          {
                            "date": "2026-10-14",
                            "slots": [
                              "13:00",
                              "13:30"
                            ]
                          }
                        ]
                      }
                    },
                    "locker_cabinets": [],
                    "tab": null,
                    "login_required": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "order_type": {
                    "type": "string"
                  },
                  "latitude": {
                    "type": "number"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "postcode": {
                    "type": "string"
                  },
                  "requested_at": {
                    "type": "string"
                  },
                  "tip": {
                    "type": "number"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "shelf_id": {
                    "type": "integer"
                  },
                  "table_code": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "order_type": "delivery",
                "postcode": "H2X 2Z2"
              }
            }
          }
        },
        "x-route-name": "openapp.guest.store.checkout.quote",
        "x-graphql": "platformAppGuestStoreCheckoutQuote",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/stores/{slug}/checkout/place": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Place a guest order where the store takes guest orders (or at a table)",
        "description": "Place a guest order where the store takes guest orders (or at a table); answers the order, the payment and the guest order token. Guests: X-Guest-Cart-Token names the cart; keep guest_order_token on the device and send it as X-Guest-Order-Token. payment.method stripe: present the PaymentSheet with client_secret / publishable_key / merchant_country / merchant_display_name, then call confirm-payment; offline and tab: nothing to pay in the app. Errors: 404 STORE_NOT_FOUND, 422 CART_EMPTY, 403 LOGIN_REQUIRED (guest where the store takes no guest orders), 422 ORDER_TYPE_UNAVAILABLE, 422 TABLE_REQUIRED, 422 TABLE_NOT_FOUND, 422 CHECKOUT_VALIDATION_FAILED with errors[] (price_changed, out_of_delivery_area, store_closed, item_unavailable, cabinet_required, invalid_time_slot, below_min_order, ...), 422 PAYMENT_METHOD_UNAVAILABLE, 422 PAYMENT_ERROR, 500 CHECKOUT_FAILED, 422 VALIDATION_FAILED. CHECKOUT_VALIDATION_FAILED also carries reasons: an object {code: message} with the same codes as errors, each with the message the web checkout shows for it in the answer language (an unforeseen code gets the general message); errors stays the list of codes. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreCheckoutPlace",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "bistro"
            }
          },
          {
            "name": "X-Guest-Cart-Token",
            "in": "header",
            "required": false,
            "description": "The guest's cart token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "code": "EQ0MS2",
                      "kind": "store_order",
                      "store": {
                        "id": 31,
                        "slug": "bistro",
                        "name": "Bistro",
                        "logo_url": null
                      },
                      "order_type": "delivery",
                      "status": "pending_payment",
                      "status_label": "Pending payment",
                      "fulfillment_status": "new",
                      "fulfillment_label": "New",
                      "paid": false,
                      "total": 29.0,
                      "currency": "CAD",
                      "items_count": 2,
                      "table_code": null,
                      "created_at": "2026-10-14T12:00:00-04:00",
                      "channel": "app",
                      "requested_at": null,
                      "promised_at": "2026-10-14T12:35:00-04:00",
                      "paid_at": null,
                      "subtotal": 25.0,
                      "delivery_fee": 4.0,
                      "tax": 0.0,
                      "tip": 0.0,
                      "discount": 0.0,
                      "coupon_code": null,
                      "refunded_amount": 0.0,
                      "payment_method": "stripe",
                      "contact": {
                        "name": "Ada",
                        "telephone": "+15145550100",
                        "email": "ada@example.com"
                      },
                      "address": {
                        "address_1": "10 Rue Test",
                        "address_2": null,
                        "city": "Montreal",
                        "province": "QC",
                        "country": "CA",
                        "postcode": "H2X 2Z2",
                        "latitude": 45.51,
                        "longitude": -73.57
                      },
                      "delivery_instruction": null,
                      "note": null,
                      "items": [
                        {
                          "id": 1,
                          "product_id": 41,
                          "product_variant_id": null,
                          "name": "Burger",
                          "qty": 2,
                          "refunded_qty": 0,
                          "unit_price": 12.5,
                          "total": 25.0,
                          "options": [],
                          "review_rating": null
                        }
                      ],
                      "events": [
                        {
                          "track": "status",
                          "from": null,
                          "to": "pending_payment",
                          "at": "2026-10-14T12:00:00-04:00"
                        },
                        {
                          "track": "status",
                          "from": "pending_payment",
                          "to": "paid",
                          "at": "2026-10-14T12:01:10-04:00"
                        }
                      ],
                      "tracking_number": null,
                      "locker": null,
                      "actions": {
                        "can_pay": true,
                        "can_cancel": true,
                        "can_reorder": true,
                        "can_return": true,
                        "return_pending": false,
                        "can_review": true
                      },
                      "web_url": "https://shop.example.com/account/order/EQ0MS2"
                    },
                    "payment": {
                      "method": "stripe",
                      "client_secret": "pi_3Q_secret_abc",
                      "publishable_key": "pk_live_123",
                      "merchant_country": "CA",
                      "merchant_display_name": "Bistro",
                      "amount": 29.0,
                      "currency": "CAD"
                    },
                    "tab": null,
                    "guest_order_token": "3f0c6c1b2b8e4d0a9a1e6f5d4c3b2a19087f6e5d4c3b2a1908f7e6d5c4b3a291"
                  }
                }
              }
            }
          },
          "422": {
            "description": "CHECKOUT_VALIDATION_FAILED (and the other 422 codes listed above)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "CHECKOUT_VALIDATION_FAILED",
                  "message": "Please check your order and address.",
                  "errors": [
                    "price_changed",
                    "out_of_delivery_area"
                  ],
                  "reasons": {
                    "price_changed": "Some prices have changed. Please review your cart.",
                    "out_of_delivery_area": "Sorry, this store does not deliver to your address."
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "STORE_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "order_type": {
                    "type": "string",
                    "enum": [
                      "delivery",
                      "collection",
                      "dine_in",
                      "locker"
                    ]
                  },
                  "name": {
                    "type": "string"
                  },
                  "telephone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "address_1": {
                    "type": "string"
                  },
                  "address_2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "province": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string"
                  },
                  "postcode": {
                    "type": "string"
                  },
                  "latitude": {
                    "type": "number"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "delivery_instruction": {
                    "type": "string"
                  },
                  "note": {
                    "type": "string"
                  },
                  "shelf_id": {
                    "type": "integer"
                  },
                  "table_code": {
                    "type": "string"
                  },
                  "requested_at": {
                    "type": "string"
                  },
                  "tip": {
                    "type": "number"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "payment_method": {
                    "type": "string",
                    "enum": [
                      "stripe",
                      "offline"
                    ]
                  }
                }
              },
              "example": {
                "order_type": "delivery",
                "name": "Ada",
                "telephone": "+15145550100",
                "email": "ada@example.com",
                "address_1": "10 Rue Test",
                "city": "Montreal",
                "postcode": "H2X 2Z2"
              }
            }
          }
        },
        "x-route-name": "openapp.guest.store.checkout.place",
        "x-graphql": "platformAppGuestStoreCheckoutPlace",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}": {
      "get": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "One guest store order, with its order token",
        "description": "One guest store order, with its order token. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. items[].options is always a list of the option groups chosen for the line (empty without options): [{attachment_id: int|null, store_option_id: int|null, name: string, values: [{store_option_value_id: int|null, value: string, delta: number}]}] (delta = the price added per unit by that choice, already included in unit_price). locker (locker pickup orders, else null): {cabinet, address, pickup_code, pickup_due_at, remaining, items, door_open, can_open, refund_available}; locker.items is always a list of the order's cells: [{id: int, name: string, status: string (sold = waiting to be opened, opened = door open now, collected, expired, removed), compartment_number: string|null (the lock board's door number), pickup_number: int|null (the number shown on the door)}]. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrder",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.store-orders.show",
        "x-graphql": "platformAppGuestStoreOrder",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/pay": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Pay a guest order whose payment was left unfinished",
        "description": "Pay a guest order whose payment was left unfinished: the same payment object as place. Guests: send the order token as X-Guest-Order-Token. Keeps the order's PaymentIntent while Stripe still accepts it (reused_intent true), otherwise starts a new one as checkout does; present the PaymentSheet, then call confirm-payment. Only while actions.can_pay is true. Errors: 404 ORDER_NOT_FOUND, 409 NOT_AWAITING_PAYMENT (paid, cancelled, refunded, a tab round or paid at the counter), 409 ORDER_ALREADY_PAID (the intent had already succeeded: the order is settled now, data carries it), 422 PAYMENT_ERROR. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderPay",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "order": {
                      "code": "EQ0MS2",
                      "kind": "store_order",
                      "store": {
                        "id": 31,
                        "slug": "bistro",
                        "name": "Bistro",
                        "logo_url": null
                      },
                      "order_type": "delivery",
                      "status": "pending_payment",
                      "status_label": "Pending payment",
                      "fulfillment_status": "new",
                      "fulfillment_label": "New",
                      "paid": false,
                      "total": 29.0,
                      "currency": "CAD",
                      "items_count": 2,
                      "table_code": null,
                      "created_at": "2026-10-14T12:00:00-04:00",
                      "channel": "app",
                      "requested_at": null,
                      "promised_at": "2026-10-14T12:35:00-04:00",
                      "paid_at": null,
                      "subtotal": 25.0,
                      "delivery_fee": 4.0,
                      "tax": 0.0,
                      "tip": 0.0,
                      "discount": 0.0,
                      "coupon_code": null,
                      "refunded_amount": 0.0,
                      "payment_method": "stripe",
                      "contact": {
                        "name": "Ada",
                        "telephone": "+15145550100",
                        "email": "ada@example.com"
                      },
                      "address": {
                        "address_1": "10 Rue Test",
                        "address_2": null,
                        "city": "Montreal",
                        "province": "QC",
                        "country": "CA",
                        "postcode": "H2X 2Z2",
                        "latitude": 45.51,
                        "longitude": -73.57
                      },
                      "delivery_instruction": null,
                      "note": null,
                      "items": [
                        {
                          "id": 1,
                          "product_id": 41,
                          "product_variant_id": null,
                          "name": "Burger",
                          "qty": 2,
                          "refunded_qty": 0,
                          "unit_price": 12.5,
                          "total": 25.0,
                          "options": [],
                          "review_rating": null
                        }
                      ],
                      "events": [
                        {
                          "track": "status",
                          "from": null,
                          "to": "pending_payment",
                          "at": "2026-10-14T12:00:00-04:00"
                        },
                        {
                          "track": "status",
                          "from": "pending_payment",
                          "to": "paid",
                          "at": "2026-10-14T12:01:10-04:00"
                        }
                      ],
                      "tracking_number": null,
                      "locker": null,
                      "actions": {
                        "can_pay": true,
                        "can_cancel": true,
                        "can_reorder": true,
                        "can_return": true,
                        "return_pending": false,
                        "can_review": true
                      },
                      "web_url": "https://shop.example.com/account/order/EQ0MS2"
                    },
                    "payment": {
                      "method": "stripe",
                      "client_secret": "pi_3Q_secret_abc",
                      "publishable_key": "pk_live_123",
                      "merchant_country": "CA",
                      "merchant_display_name": "Bistro",
                      "amount": 29.0,
                      "currency": "CAD"
                    },
                    "reused_intent": true
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.store-orders.pay",
        "x-graphql": "platformAppGuestStoreOrderPay",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/confirm-payment": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "After the PaymentSheet, for a guest order",
        "description": "After the PaymentSheet, for a guest order: ask Stripe and settle the order once. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderConfirmPayment",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "paid": true,
                    "order": {
                      "code": "EQ0MS2",
                      "kind": "store_order",
                      "store": {
                        "id": 31,
                        "slug": "bistro",
                        "name": "Bistro",
                        "logo_url": null
                      },
                      "order_type": "delivery",
                      "status": "paid",
                      "status_label": "Paid",
                      "fulfillment_status": "new",
                      "fulfillment_label": "New",
                      "paid": true,
                      "total": 29.0,
                      "currency": "CAD",
                      "items_count": 2,
                      "table_code": null,
                      "created_at": "2026-10-14T12:00:00-04:00",
                      "channel": "app",
                      "requested_at": null,
                      "promised_at": "2026-10-14T12:35:00-04:00",
                      "paid_at": "2026-10-14T12:01:10-04:00",
                      "subtotal": 25.0,
                      "delivery_fee": 4.0,
                      "tax": 0.0,
                      "tip": 0.0,
                      "discount": 0.0,
                      "coupon_code": null,
                      "refunded_amount": 0.0,
                      "payment_method": "stripe",
                      "contact": {
                        "name": "Ada",
                        "telephone": "+15145550100",
                        "email": "ada@example.com"
                      },
                      "address": {
                        "address_1": "10 Rue Test",
                        "address_2": null,
                        "city": "Montreal",
                        "province": "QC",
                        "country": "CA",
                        "postcode": "H2X 2Z2",
                        "latitude": 45.51,
                        "longitude": -73.57
                      },
                      "delivery_instruction": null,
                      "note": null,
                      "items": [
                        {
                          "id": 1,
                          "product_id": 41,
                          "product_variant_id": null,
                          "name": "Burger",
                          "qty": 2,
                          "refunded_qty": 0,
                          "unit_price": 12.5,
                          "total": 25.0,
                          "options": [],
                          "review_rating": null
                        }
                      ],
                      "events": [
                        {
                          "track": "status",
                          "from": null,
                          "to": "pending_payment",
                          "at": "2026-10-14T12:00:00-04:00"
                        },
                        {
                          "track": "status",
                          "from": "pending_payment",
                          "to": "paid",
                          "at": "2026-10-14T12:01:10-04:00"
                        }
                      ],
                      "tracking_number": null,
                      "locker": null,
                      "actions": {
                        "can_pay": false,
                        "can_cancel": true,
                        "can_reorder": true,
                        "can_return": true,
                        "return_pending": false,
                        "can_review": true
                      },
                      "web_url": "https://shop.example.com/account/order/EQ0MS2"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.store-orders.confirm-payment",
        "x-graphql": "platformAppGuestStoreOrderConfirmPayment",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/cancel": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Cancel a guest order before the store accepts it",
        "description": "Cancel a guest order before the store accepts it. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. 409 CANCEL_NOT_ALLOWED, 422 CANCEL_FAILED. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderCancel",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Your order has been cancelled and refunded.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "refunded",
                    "status_label": "Refunded",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.store-orders.cancel",
        "x-graphql": "platformAppGuestStoreOrderCancel",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/locker-refund": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Refund a guest's locker pickup whose door never opened",
        "description": "Refund a guest's locker pickup whose door never opened. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. 409 NOT_A_LOCKER_ORDER, 404 CABINET_NOT_FOUND, 409 REFUND_REFUSED. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderLockerRefund",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Refund issued.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.store-orders.locker-refund",
        "x-graphql": "platformAppGuestStoreOrderLockerRefund",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/reorder": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Put a guest order's lines back into the guest cart",
        "description": "Put a guest order's lines back into the guest cart; answers the cart token. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderReorder",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Cart-Token",
            "in": "header",
            "required": false,
            "description": "The guest's cart token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "The items were added to your cart.",
                  "data": {
                    "added": 1,
                    "skipped": 0,
                    "store_slug": "bistro",
                    "cart_token": "Yx8kLm2Qp9TzR4vB7nC1dF6gH3jK5wE0aS8uI2oP"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.store-orders.reorder",
        "x-graphql": "platformAppGuestStoreOrderReorder",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/return": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Ask the store to take a guest's paid or completed order back",
        "description": "Ask the store to take a guest's paid or completed order back. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. 409 RETURN_NOT_ALLOWED, 409 RETURN_ALREADY_OPEN, 422 VALIDATION_FAILED. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderReturn",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Return requested.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              },
              "example": {
                "reason": "Cold on arrival"
              }
            }
          }
        },
        "x-route-name": "openapp.guest.store-orders.return",
        "x-graphql": "platformAppGuestStoreOrderReturn",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/store-orders/{code}/review/{productId}": {
      "post": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "Rate one product of a guest order",
        "description": "Rate one product of a guest order. Guests: send the order token as X-Guest-Order-Token. Errors: 404 ORDER_NOT_FOUND. 404 PRODUCT_NOT_IN_ORDER, 422 VALIDATION_FAILED. Answered exactly as the internal route.",
        "operationId": "platformAppGuestStoreOrderReview",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "The order code.",
            "schema": {
              "type": "string",
              "example": "EQ0MS2"
            }
          },
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 41
            }
          },
          {
            "name": "X-Guest-Order-Token",
            "in": "header",
            "required": true,
            "description": "The guest_order_token returned by place.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "message": "Thanks for your review.",
                  "data": {
                    "code": "EQ0MS2",
                    "kind": "store_order",
                    "store": {
                      "id": 31,
                      "slug": "bistro",
                      "name": "Bistro",
                      "logo_url": null
                    },
                    "order_type": "delivery",
                    "status": "paid",
                    "status_label": "Paid",
                    "fulfillment_status": "new",
                    "fulfillment_label": "New",
                    "paid": true,
                    "total": 29.0,
                    "currency": "CAD",
                    "items_count": 2,
                    "table_code": null,
                    "created_at": "2026-10-14T12:00:00-04:00",
                    "channel": "app",
                    "requested_at": null,
                    "promised_at": "2026-10-14T12:35:00-04:00",
                    "paid_at": "2026-10-14T12:01:10-04:00",
                    "subtotal": 25.0,
                    "delivery_fee": 4.0,
                    "tax": 0.0,
                    "tip": 0.0,
                    "discount": 0.0,
                    "coupon_code": null,
                    "refunded_amount": 0.0,
                    "payment_method": "stripe",
                    "contact": {
                      "name": "Ada",
                      "telephone": "+15145550100",
                      "email": "ada@example.com"
                    },
                    "address": {
                      "address_1": "10 Rue Test",
                      "address_2": null,
                      "city": "Montreal",
                      "province": "QC",
                      "country": "CA",
                      "postcode": "H2X 2Z2",
                      "latitude": 45.51,
                      "longitude": -73.57
                    },
                    "delivery_instruction": null,
                    "note": null,
                    "items": [
                      {
                        "id": 1,
                        "product_id": 41,
                        "product_variant_id": null,
                        "name": "Burger",
                        "qty": 2,
                        "refunded_qty": 0,
                        "unit_price": 12.5,
                        "total": 25.0,
                        "options": [],
                        "review_rating": null
                      }
                    ],
                    "events": [
                      {
                        "track": "status",
                        "from": null,
                        "to": "pending_payment",
                        "at": "2026-10-14T12:00:00-04:00"
                      },
                      {
                        "track": "status",
                        "from": "pending_payment",
                        "to": "paid",
                        "at": "2026-10-14T12:01:10-04:00"
                      }
                    ],
                    "tracking_number": null,
                    "locker": null,
                    "actions": {
                      "can_pay": false,
                      "can_cancel": true,
                      "can_reorder": true,
                      "can_return": true,
                      "return_pending": false,
                      "can_review": true
                    },
                    "web_url": "https://shop.example.com/account/order/EQ0MS2"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rating": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "comment": {
                    "type": "string",
                    "maxLength": 2000
                  }
                }
              },
              "example": {
                "rating": 5,
                "comment": "Good"
              }
            }
          }
        },
        "x-route-name": "openapp.guest.store-orders.review",
        "x-graphql": "platformAppGuestStoreOrderReview",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/mall/home": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mall home blocks (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). The blocks the client shows on the mall home, in the client's order: `banners`, `categories`, `group_buys`, `coupons`, `featured_stores`, `featured_products`, `stores` (first 12 of the directory). An empty block is left out; `group_buys` is left out when the app's group_buy capability is off. Without mall operations or without a mall: `directory_only: true` and no blocks — show mall/stores. 404 STOREFRONT_UNAVAILABLE when the client has no marketplace. Every product card carries currency: the currency code its prices are in (the store's Client's). Answered exactly as the internal route.",
        "operationId": "platformAppGuestMallHome",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "directory_only": false,
                    "blocks": [
                      {
                        "key": "categories",
                        "items": [
                          {
                            "id": 1,
                            "name": "Food",
                            "children": [
                              {
                                "id": 2,
                                "name": "Pizza"
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "key": "group_buys",
                        "items": [
                          {
                            "code": "PZBOX7",
                            "title": "Friday pizza box",
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "opens_at": "2026-10-14T14:00:00-04:00",
                            "cutoff_at": "2026-10-16T15:00:00-04:00",
                            "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                          }
                        ]
                      },
                      {
                        "key": "coupons",
                        "items": [
                          {
                            "id": 1,
                            "name": "5 off your first order",
                            "description": "Orders over 30",
                            "code": "WELCOME5",
                            "ends_on": "2026-12-31"
                          }
                        ]
                      },
                      {
                        "key": "featured_stores",
                        "items": [
                          {
                            "id": 1,
                            "slug": "pizza-place-1",
                            "name": "Pizza Place",
                            "description": "",
                            "store_type": "restaurant",
                            "store_type_label": "Restaurant",
                            "tags": [
                              "pizza",
                              "halal"
                            ],
                            "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                            "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                            "rating_avg": 4.6,
                            "rating_count": 38,
                            "address": "12 King St W",
                            "city": "Toronto"
                          }
                        ]
                      },
                      {
                        "key": "featured_products",
                        "items": [
                          {
                            "id": 1,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Margherita",
                            "description": "Tomato, mozzarella, basil",
                            "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                            "price": 12,
                            "list_price": 14,
                            "compare_at_price": 14,
                            "on_sale": true,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [
                              {
                                "code": "gluten",
                                "label": "Gluten"
                              },
                              {
                                "code": "milk",
                                "label": "Milk"
                              }
                            ],
                            "affiliate": false,
                            "external_url": null
                          }
                        ]
                      },
                      {
                        "key": "stores",
                        "items": [
                          {
                            "id": 1,
                            "slug": "pizza-place-1",
                            "name": "Pizza Place",
                            "description": "",
                            "store_type": "restaurant",
                            "store_type_label": "Restaurant",
                            "tags": [
                              "pizza",
                              "halal"
                            ],
                            "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                            "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                            "rating_avg": 4.6,
                            "rating_count": 38,
                            "address": "12 King St W",
                            "city": "Toronto"
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.mall.home",
        "x-graphql": "platformAppGuestMallHome",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/mall/stores": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Store directory (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). Every listed store in the mall (every listed store of the client when it has no mall), in the client's order then by rating; filters by store type, tag (case-insensitive) and words (name, names in other languages, tags); 24 a page. `facets` lists the types and tags with their store counts, computed over all stores. Answered exactly as the internal route.",
        "operationId": "platformAppGuestMallStores",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Store type, e.g. restaurant"
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "One store tag"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Words, at most 100 characters"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "stores": [
                      {
                        "id": 1,
                        "slug": "pizza-place-1",
                        "name": "Pizza Place",
                        "description": "",
                        "store_type": "restaurant",
                        "store_type_label": "Restaurant",
                        "tags": [
                          "pizza",
                          "halal"
                        ],
                        "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                        "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                        "rating_avg": 4.6,
                        "rating_count": 38,
                        "address": "12 King St W",
                        "city": "Toronto"
                      }
                    ],
                    "facets": {
                      "types": [
                        {
                          "type": "restaurant",
                          "label": "Restaurant",
                          "count": 1
                        }
                      ],
                      "tags": [
                        {
                          "tag": "pizza",
                          "count": 1
                        },
                        {
                          "tag": "halal",
                          "count": 1
                        }
                      ]
                    },
                    "filters": {
                      "type": "",
                      "tag": "pizza",
                      "q": ""
                    },
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 24,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.mall.stores",
        "x-graphql": "platformAppGuestMallStores",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/mall/search": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mall search (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). Stores whose name, other-language names or tags contain the words, and listed products whose name contains them, grouped by store (at most 60 products). Empty words: empty lists. Needs a mall with operations: 404 MALL_UNAVAILABLE otherwise. Every product card carries currency: the currency code its prices are in (the store's Client's). Answered exactly as the internal route.",
        "operationId": "platformAppGuestMallSearch",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "marg"
            },
            "description": "Words, at most 100 characters"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "q": "marg",
                    "stores": [],
                    "products_by_store": [
                      {
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place",
                          "description": "",
                          "store_type": "restaurant",
                          "store_type_label": "Restaurant",
                          "tags": [
                            "pizza",
                            "halal"
                          ],
                          "logo_url": "https://shop.example.com/storage/stores/31/logo.png",
                          "cover_url": "https://shop.example.com/storage/stores/31/cover.jpg",
                          "rating_avg": 4.6,
                          "rating_count": 38,
                          "address": "12 King St W",
                          "city": "Toronto"
                        },
                        "products": [
                          {
                            "id": 1,
                            "store": {
                              "id": 1,
                              "slug": "pizza-place-1",
                              "name": "Pizza Place"
                            },
                            "name": "Margherita",
                            "description": "Tomato, mozzarella, basil",
                            "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                            "price": 12,
                            "list_price": 14,
                            "compare_at_price": 14,
                            "on_sale": true,
                            "currency": "CAD",
                            "available": true,
                            "within_mealtimes": true,
                            "mealtimes": [],
                            "allergens": [
                              {
                                "code": "gluten",
                                "label": "Gluten"
                              },
                              {
                                "code": "milk",
                                "label": "Milk"
                              }
                            ],
                            "affiliate": false,
                            "external_url": null
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.mall.search",
        "x-graphql": "platformAppGuestMallSearch",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/mall/categories/{categoryId}": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Mall category products (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). One active mall category (a top category includes its sub-categories) and one page of its products, 24 a page, each with its own store. Needs a mall with operations. Every product card carries currency: the currency code its prices are in (the store's Client's). Answered exactly as the internal route.",
        "operationId": "platformAppGuestMallCategory",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "categoryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "category": {
                      "id": 1,
                      "name": "Food",
                      "children": [
                        {
                          "id": 2,
                          "name": "Pizza"
                        }
                      ],
                      "parent": null
                    },
                    "products": [
                      {
                        "id": 1,
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "name": "Margherita",
                        "description": "Tomato, mozzarella, basil",
                        "image_url": "https://shop.example.com/storage/products/88/margherita.jpg",
                        "price": 12,
                        "list_price": 14,
                        "compare_at_price": 14,
                        "on_sale": true,
                        "currency": "CAD",
                        "available": true,
                        "within_mealtimes": true,
                        "mealtimes": [],
                        "allergens": [
                          {
                            "code": "gluten",
                            "label": "Gluten"
                          },
                          {
                            "code": "milk",
                            "label": "Milk"
                          }
                        ],
                        "affiliate": false,
                        "external_url": null
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "last_page": 1,
                      "per_page": 24,
                      "total": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.mall.category",
        "x-graphql": "platformAppGuestMallCategory",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/mall/group-buys": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Group buy channel (guest)",
        "description": "Public, no sign-in: a guest of the client behind clientCode (A6). The group buys buyers may order now, soonest cutoff first; each `url` opens its page on the client's white-label host. In a mall with operations `category` narrows them to those carrying a product of that mall category and `categories` is the tree to choose from; otherwise the group buys of every listed store and no categories. Empty when the app's group_buy capability is off. Answered exactly as the internal route.",
        "operationId": "platformAppGuestMallGroupBuys",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Mall category id"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages; signed in, the account language is the default.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "group_buys": [
                      {
                        "code": "PZBOX7",
                        "title": "Friday pizza box",
                        "store": {
                          "id": 1,
                          "slug": "pizza-place-1",
                          "name": "Pizza Place"
                        },
                        "opens_at": "2026-10-14T14:00:00-04:00",
                        "cutoff_at": "2026-10-16T15:00:00-04:00",
                        "url": "https://shop.example.com/portal/group-buy/PZBOX7"
                      }
                    ],
                    "categories": [
                      {
                        "id": 1,
                        "name": "Food",
                        "children": [
                          {
                            "id": 2,
                            "name": "Pizza"
                          }
                        ]
                      }
                    ],
                    "category_id": 0
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: no such app, client or the client is inactive (one answer for all three)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.mall.group-buys",
        "x-graphql": "platformAppGuestMallGroupBuys",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/links/resolve": {
      "get": {
        "tags": [
          "Platform Apps",
          "App Storefront"
        ],
        "summary": "What a scanned link of the client opens in the app, without signing in",
        "description": "What a scanned link of the client opens in the app, without signing in. Accepts the client's white-label host and the platform host (mall by /m/{code}); kind is store | store_table | store_category (slug, category_id: a category page of the multi-page style, added with docs/STORE-STYLES-DESIGN.md P2) | product | mall (page home|stores|search|group_buy) | mall_category | group_buy (campaign_code, leader_code) | unknown. 404 APP_CONTEXT_NOT_FOUND for an unknown app/client (guest). Answered exactly as the internal route.",
        "operationId": "platformAppGuestLinkResolve",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "https://shop.example.com/s/bistro/t/5"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Answer language, one of the 14 platform languages.",
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "kind": "store_table",
                    "slug": "bistro",
                    "table_code": "T5",
                    "campaign_code": null,
                    "leader_code": null,
                    "category_id": null,
                    "product_id": null,
                    "page": null
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": false,
                  "code": "APP_CONTEXT_NOT_FOUND",
                  "message": "Order not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.links.resolve",
        "x-graphql": "platformAppGuestLinkResolve",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/guest/clients": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "List the providers a visitor may use without signing in",
        "description": "Public. The Clients of an app that answer without an account, each with features: quotes, when the app's quotes.public capability is on for the Client and public quotes are switched on in its Customer Portal; shipping, when the Client takes guest shipments (guest.shipping), in which case guest_shipping lists the kinds offered (self_delivery, label) and the verification_channel (email or phone). Sorted by display name. Answered exactly as the internal route.",
        "operationId": "platformAppGuestClients",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Providers available without an account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestClients"
                },
                "example": {
                  "result": true,
                  "data": {
                    "app": {
                      "code": "customer",
                      "name": "SuperRoute"
                    },
                    "count": 1,
                    "items": [
                      {
                        "client_code": "n4x7q2g8w9r3k6m1p5t0z8ab",
                        "display_name": "Northstar Courier",
                        "logo_url": null,
                        "primary_color": "#E02020",
                        "features": [
                          "quotes"
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: app not found or not active"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.clients",
        "x-graphql": "platformAppGuestClients",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/verify/request": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Send a guest a verification code",
        "description": "Public. Sends a six-digit code to an email address or a phone number, on the channel the Client chose for guest shipping (settings guest.verification_channel; shown in GET /v1/apps/{appCode}/guest/clients). The answer is the same for any contact. The code expires in 10 minutes; one code per contact and Client per minute and 20 per IP address per hour. Answered exactly as the internal route.",
        "operationId": "platformAppGuestVerifyRequest",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "contact": "guest@example.com",
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestVerifyRequested"
                },
                "example": {
                  "result": true,
                  "message": "A verification code was sent.",
                  "challenge_id": "Qm9vZ2llV29vZ2llQm9vZ2llV29vZ2llQm9vZ2llV29vZ2llQm9vZ2llV29vZ2ll",
                  "channel": "email",
                  "contact": "g****@example.com",
                  "expires_in": 600,
                  "resend_after": 60
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: the Client does not offer guest shipping in this app"
          },
          "422": {
            "description": "INVALID_EMAIL or INVALID_PHONE_NUMBER"
          },
          "429": {
            "description": "GUEST_VERIFICATION_RATE_LIMITED"
          },
          "503": {
            "description": "SMS_SERVICE_NOT_CONFIGURED, EMAIL_DELIVERY_FAILED or SMS_DELIVERY_FAILED"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.verify.request",
        "x-graphql": "platformAppGuestVerifyRequest",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/clients/{clientCode}/guest/verify/complete": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Check a guest verification code",
        "description": "Public. Checks the code of a challenge and returns a contact token: proof, for 20 minutes and at this Client only, that the guest holds the contact. It is not a sign-in, and a sign-in token is never accepted in its place. Five wrong codes void the challenge. Answered exactly as the internal route.",
        "operationId": "platformAppGuestVerifyComplete",
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "challenge_id": "Qm9vZ2llV29vZ2llQm9vZ2llV29vZ2llQm9vZ2llV29vZ2llQm9vZ2llV29vZ2ll",
                "code": "482913"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contact verified",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAppGuestContactToken"
                },
                "example": {
                  "result": true,
                  "contact_token": "eyJpdiI6IkNvbnRhY3RUb2tlbiIs...",
                  "channel": "email",
                  "contact": "g****@example.com",
                  "expires_in": 1200
                }
              }
            }
          },
          "404": {
            "description": "APP_CONTEXT_NOT_FOUND: the Client does not offer guest shipping in this app"
          },
          "422": {
            "description": "INVALID_VERIFICATION_CODE, VERIFICATION_ATTEMPTS_EXCEEDED or INVALID_VERIFICATION_CHALLENGE"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.guest.verify.complete",
        "x-graphql": "platformAppGuestVerifyComplete",
        "security": [
          {
            "partnerAppKey": []
          }
        ]
      }
    },
    "/app/v1/profile": {
      "get": {
        "summary": "GET /app/v1/profile",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.profile.get",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerProfileGet"
      },
      "post": {
        "summary": "POST /app/v1/profile",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.profile.post",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerProfilePost"
      }
    },
    "/app/v1/address-by-postcode/{postcode}": {
      "get": {
        "summary": "GET /app/v1/address-by-postcode/{postcode}",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.address-by-postcode.postcode.get",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerAddressByPostcodePostcodeGet"
      }
    },
    "/app/v1/address-by-postcode/{postcode?}": {
      "post": {
        "summary": "POST /app/v1/address-by-postcode/{postcode?}",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.address-by-postcode.postcode.post",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerAddressByPostcodePostcodePost"
      }
    },
    "/app/v1/order-addressbook": {
      "get": {
        "summary": "GET /app/v1/order-addressbook",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.order-addressbook.get",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerOrderAddressbookGet"
      },
      "post": {
        "summary": "POST /app/v1/order-addressbook",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.order-addressbook.post",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerOrderAddressbookPost"
      }
    },
    "/app/v1/order-addressbook/{id}": {
      "get": {
        "summary": "GET /app/v1/order-addressbook/{id}",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.order-addressbook.id.get",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerOrderAddressbookIdGet"
      },
      "put": {
        "summary": "PUT /app/v1/order-addressbook/{id}",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.order-addressbook.id.put",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerOrderAddressbookIdPut"
      },
      "delete": {
        "summary": "DELETE /app/v1/order-addressbook/{id}",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.order-addressbook.id.delete",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerOrderAddressbookIdDelete"
      }
    },
    "/app/v1/saved-form-answers": {
      "get": {
        "operationId": "customerSavedFormAnswersList",
        "tags": [
          "Customer"
        ],
        "summary": "List the order forms whose answers the customer may keep on their account",
        "description": "Every active form the client bound to an order type with `remember_answers` on, with its fields and the answers this customer saved. The order-form config bundles return the same answers as `saved_form_answers` for prefilling a new order. Answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Forms with saved answers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "form_id": {
                            "type": "integer",
                            "example": 3
                          },
                          "form_code": {
                            "type": "string",
                            "example": "contact_info"
                          },
                          "form_name": {
                            "type": "string",
                            "example": "Contact Info"
                          },
                          "fields": {
                            "type": "array",
                            "description": "The form's fields, same shape as form_bindings[].fields in the order-form config bundles.",
                            "items": {
                              "type": "object"
                            }
                          },
                          "answers": {
                            "type": "object",
                            "description": "Field code → string or list of strings; an empty object when nothing is saved.",
                            "example": {
                              "wechat": "wx_alice"
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": [
                    {
                      "form_id": 3,
                      "form_code": "contact_info",
                      "form_name": "Contact Info",
                      "fields": [
                        {
                          "code": "wechat",
                          "name": "WeChat ID / WhatsApp ID",
                          "type": "text",
                          "required": true,
                          "display_name": {
                            "en": "WeChat ID / WhatsApp ID",
                            "chs": "微信ID 或 WhatsApp ID"
                          },
                          "options": [],
                          "default_value": "",
                          "sort_order": 0
                        }
                      ],
                      "answers": {
                        "wechat": "wx_alice"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.saved-form-answers.get",
        "x-graphql": "customerSavedFormAnswers"
      }
    },
    "/app/v1/saved-form-answers/{formId}": {
      "put": {
        "operationId": "customerSavedFormAnswersSave",
        "tags": [
          "Customer"
        ],
        "summary": "Save the answers the customer keeps for one order form",
        "description": "Replaces the saved answers for the form. Only the form's own field codes are kept, as trimmed strings or lists of strings (at most 1000 characters each); blanks are dropped. Answers that end up empty remove the saved entry. Saving here never changes an order. Answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Form id (form_bindings[].form_id)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "answers"
                ],
                "properties": {
                  "answers": {
                    "type": "object",
                    "description": "Field code → string or list of strings",
                    "example": {
                      "wechat": "wx_alice"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "form_id": {
                          "type": "integer",
                          "example": 3
                        },
                        "form_code": {
                          "type": "string",
                          "example": "contact_info"
                        },
                        "form_name": {
                          "type": "string",
                          "example": "Contact Info"
                        },
                        "fields": {
                          "type": "array",
                          "description": "The form's fields, same shape as form_bindings[].fields in the order-form config bundles.",
                          "items": {
                            "type": "object"
                          }
                        },
                        "answers": {
                          "type": "object",
                          "description": "Field code → string or list of strings; an empty object when nothing is saved.",
                          "example": {
                            "wechat": "wx_alice"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The form is not one the customer may keep answers for",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Form not found."
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`answers` is not an object",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "The answers must be an object of field codes."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.saved-form-answers.formId.put",
        "x-graphql": "customerSaveFormAnswers"
      },
      "delete": {
        "operationId": "customerSavedFormAnswersDelete",
        "tags": [
          "Customer"
        ],
        "summary": "Remove the answers the customer keeps for one order form",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Form id (form_bindings[].form_id)"
          }
        ],
        "responses": {
          "200": {
            "description": "Removed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The form is not one the customer may keep answers for",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Form not found."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.saved-form-answers.formId.delete",
        "x-graphql": "customerDeleteSavedFormAnswers",
        "description": "Answered exactly as the internal customer route."
      }
    },
    "/app/v1/storage-orders/config": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Get the configuration bundle needed to render the customer 'create storage order' form",
        "description": "Returns everything the client needs to render the customer-side create storage order form: the customer's accessible warehouses, the business's packaging catalog, supplies products, pickup timeframes, unit definitions, surcharges, and dynamic form bindings. Requires an authenticated customer account. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Config bundle",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "warehouses": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "address": {
                                "type": "string"
                              },
                              "city": {
                                "type": "string"
                              },
                              "province": {
                                "type": "string"
                              },
                              "postcode": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "packagings": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "display_names": {
                                "type": "object",
                                "description": "Packaging name per language code (en, chs, cht, fr…) as the client entered it; empty languages are left out. Show the entry for the app's language, falling back to `name`.",
                                "example": {
                                  "en": "A1. Carry-on luggage",
                                  "chs": "A1. 手提行李箱"
                                }
                              },
                              "type": {
                                "type": "string"
                              },
                              "length": {
                                "type": "number"
                              },
                              "width": {
                                "type": "number"
                              },
                              "height": {
                                "type": "number"
                              },
                              "dimension_unit": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        "products": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "display_names": {
                                "type": "object"
                              },
                              "price": {
                                "type": "number"
                              },
                              "type": {
                                "type": "string"
                              },
                              "image": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "pickup_timeframes": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "dimension_units": {
                          "type": "object",
                          "description": "Keyed by int ID → {name, accuracy}"
                        },
                        "weight_units": {
                          "type": "object",
                          "description": "Keyed by int ID → {name, accuracy}"
                        },
                        "default_dimension_unit": {
                          "type": "integer",
                          "nullable": true,
                          "description": "The unit a new order form opens with: the client's customer default (Unit Settings) when set, otherwise the customer's own display unit."
                        },
                        "default_weight_unit": {
                          "type": "integer",
                          "nullable": true,
                          "description": "The unit a new order form opens with: the client's customer default (Unit Settings) when set, otherwise the customer's own display unit."
                        },
                        "allow_custom_package": {
                          "type": "boolean"
                        },
                        "surcharges": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "object"
                              },
                              "description": {
                                "type": "object"
                              },
                              "charge_type": {
                                "type": "integer"
                              },
                              "amount": {
                                "type": "number"
                              },
                              "pricing_config": {
                                "type": "object",
                                "nullable": true
                              },
                              "display_type": {
                                "type": "string"
                              },
                              "display_options": {
                                "type": "object",
                                "nullable": true
                              },
                              "unit_label": {
                                "type": "object"
                              },
                              "is_optional": {
                                "type": "boolean"
                              }
                            }
                          }
                        },
                        "form_bindings": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "form_id": {
                                "type": "integer"
                              },
                              "form_code": {
                                "type": "string"
                              },
                              "form_name": {
                                "type": "string"
                              },
                              "is_required": {
                                "type": "boolean"
                              },
                              "remember_answers": {
                                "type": "boolean",
                                "description": "The customer may keep this form's answers on their account (see /v1/customer/saved-form-answers)."
                              },
                              "sort_order": {
                                "type": "integer"
                              },
                              "fields": {
                                "type": "array",
                                "items": {
                                  "$ref": "#/components/schemas/CustomerOrderFormField"
                                }
                              }
                            }
                          }
                        },
                        "saved_form_answers": {
                          "type": "object",
                          "description": "Answers the customer keeps on their account, keyed by form id, then field code → string or list of strings. Only forms whose binding has `remember_answers` on are included. Prefill a new order's form fields from it.",
                          "additionalProperties": {
                            "type": "object"
                          },
                          "example": {
                            "3": {
                              "wechat": "wx_alice"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.storage-orders.config.get",
        "x-graphql": "customerStorageOrderConfig",
        "x-capability": "orders.storage",
        "operationId": "customerStorageOrderConfig"
      }
    },
    "/app/v1/storage-orders/calculate-price": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerStorageOrderCalculatePrice",
        "summary": "Calculate the price of a storage order",
        "description": "Calculates the estimated price of a storage order without saving anything: storage fee for the packages over the storage period, optional pickup, delivery, supplies and supplies delivery, selected surcharges and tax. Promotions are evaluated as well: a valid coupon_code is applied first; otherwise a single matching automatic promotion is applied, or the one named by selected_promotion_id when several match. business_id and customer_id come from the authentication. pickup_channel_id / delivery_channel_id take the storage channel setting id returned by the config and detail endpoints.\n\nThe response uses the key `success` rather than `result`. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "warehouse_id",
                  "start_date",
                  "end_date"
                ],
                "properties": {
                  "warehouse_id": {
                    "type": "integer"
                  },
                  "start_date": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-10-01"
                  },
                  "end_date": {
                    "type": "string",
                    "format": "date",
                    "example": "2027-01-01"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "packaging_id": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Packaging id from the config endpoint"
                        },
                        "qty": {
                          "type": "integer",
                          "example": 1,
                          "default": 1
                        },
                        "length": {
                          "type": "number"
                        },
                        "width": {
                          "type": "number"
                        },
                        "height": {
                          "type": "number"
                        },
                        "dimension_unit": {
                          "type": "integer",
                          "description": "1=mm, 2=cm, 3=m, 4=in"
                        },
                        "weight": {
                          "type": "number",
                          "nullable": true
                        },
                        "weight_unit": {
                          "type": "integer",
                          "nullable": true,
                          "description": "1=g, 2=kg, 3=oz, 4=lb"
                        }
                      }
                    },
                    "description": "Packages to store; may be empty"
                  },
                  "products": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Supplies to buy, as {productId: quantity}; quantities of 0 are ignored"
                  },
                  "need_pickup": {
                    "type": "boolean",
                    "default": false
                  },
                  "pickup_postcode": {
                    "type": "string"
                  },
                  "pickup_country": {
                    "type": "string"
                  },
                  "pickup_channel_id": {
                    "type": "integer",
                    "description": "Storage channel setting id for the pickup"
                  },
                  "need_delivery": {
                    "type": "boolean",
                    "default": false
                  },
                  "delivery_postcode": {
                    "type": "string"
                  },
                  "delivery_country": {
                    "type": "string"
                  },
                  "delivery_channel_id": {
                    "type": "integer",
                    "description": "Storage channel setting id for the delivery"
                  },
                  "need_supplies_delivery": {
                    "type": "boolean",
                    "default": false
                  },
                  "surcharges": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "description": "Surcharge selections"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "selected_promotion_id": {
                    "type": "integer",
                    "description": "Automatic promotion to apply when several match"
                  },
                  "order_id": {
                    "type": "integer",
                    "description": "When repricing an existing order: its id. Received packages of that order are added to the price and the order's own promotion usage is not counted against limits."
                  }
                }
              },
              "example": {
                "warehouse_id": 7,
                "start_date": "2026-10-01",
                "end_date": "2027-01-01",
                "items": [
                  {
                    "packaging_id": 3,
                    "qty": 2,
                    "length": 60,
                    "width": 40,
                    "height": 40,
                    "dimension_unit": 2,
                    "weight": 12,
                    "weight_unit": 2
                  }
                ],
                "need_pickup": true,
                "pickup_postcode": "M5V2H1",
                "pickup_country": "CA",
                "pickup_channel_id": 4
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Price calculated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "price": {
                      "type": "object",
                      "additionalProperties": true,
                      "properties": {
                        "shipping_price": {
                          "type": "number",
                          "description": "Total including tax"
                        },
                        "total_price": {
                          "type": "string",
                          "example": "245.60"
                        },
                        "currency": {
                          "type": "string",
                          "example": "CAD"
                        },
                        "storage": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "pickup": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "delivery": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "products": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "supplies_delivery": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "surcharges": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      }
                    },
                    "promotion": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Present only when a promotion applies"
                    },
                    "available_promotions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "description": "Present only when automatic promotions match"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "price": {
                    "shipping_price": 245.6,
                    "total_price": "245.60",
                    "currency": "CAD",
                    "storage": {
                      "result": true,
                      "shipping_price": 180.0,
                      "currency": "CAD"
                    },
                    "pickup": {
                      "result": true,
                      "shipping_price": 65.6,
                      "currency": "CAD"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing warehouse_id, start_date or end_date, or the price could not be calculated",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "message": "Missing required fields"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Warehouse not found",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "message": "Warehouse not found"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error while calculating",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "message": "Error calculating price: ..."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.storage-orders.calculate-price.post",
        "x-capability": "orders.storage",
        "x-graphql": "customerStorageOrderCalculatePrice"
      }
    },
    "/app/v1/storage-orders": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List the authenticated customer's storage orders",
        "description": "Paginated list; mirrors admin StorageOrderController::index filter/sort semantics via StorageOrderService::getStorageOrders, scoped to the authenticated customer. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "warehouse_id",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "store_from",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "store_to",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "created_at_from",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "created_at_to",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "quick_search",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "id",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "package_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "sort_by",
            "schema": {
              "type": "string",
              "enum": [
                "created_desc",
                "expiry_asc"
              ],
              "default": "created_desc"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "description": "Laravel paginator (data[], current_page, last_page, total, per_page, ...)"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.storage-orders.get",
        "x-graphql": "customerStorageOrders",
        "x-capability": "orders.storage",
        "operationId": "customerStorageOrders"
      },
      "post": {
        "tags": [
          "Customer Storage Orders"
        ],
        "operationId": "customerStorageOrderCreate",
        "summary": "Create a storage order",
        "description": "Creates a storage order for the authenticated customer. Same fields as the storage order form; business_id and customer_id come from the authentication and are never read from the body. Supports the OPTIONAL Idempotency-Key header. Supplies (products {id: quantity}) are only the provider's own active supplies; any other product id is refused with 422 and errors.products. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. A key derived from your own stable ids. A repeated key with the same body replays the first 2xx answer (body replayed: true, header Idempotency-Replayed: true); the same key with a different body is refused 409 IDEMPOTENCY_CONFLICT; a non-2xx outcome releases the key so the request may be corrected and retried."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "The storage order form fields: warehouse, packages/items, timeframe, channel fields, and per-form form_data. The authoritative field list is the storage order form; unknown fields are ignored.",
                "properties": {
                  "quote_token": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Optional. The token of the public quote (/quotes) this order comes from. Once the order is created the quote records it; an unknown or already converted token is ignored and never fails the order.",
                    "example": "k3v9q2m8x1c7b5n4z6a0s2d8f1g3h5j7k9l2p4o6"
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created. The body carries result and the created order.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present only when the response is an Idempotency-Key replay of a previously stored outcome.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "replayed": {
                      "type": "boolean",
                      "description": "Present only on an Idempotency-Key replay"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "409": {
            "description": "Idempotency conflict: the key was already used with a different body (IDEMPOTENCY_CONFLICT), or the original request is still processing (IDEMPOTENCY_IN_PROGRESS, with Retry-After: 1).",
            "headers": {
              "Retry-After": {
                "description": "Present only on the IDEMPOTENCY_IN_PROGRESS answer: retry after this many seconds.",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.storage-orders.post",
        "x-capability": "orders.storage",
        "x-graphql": "customerStorageOrderCreate"
      }
    },
    "/app/v1/storage-orders/{id}": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Get the detail of one storage order owned by the authenticated customer",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Storage order detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string"
                        },
                        "can_edit": {
                          "type": "boolean",
                          "description": "True when the customer may edit the order in its current status."
                        },
                        "can_cancel": {
                          "type": "boolean",
                          "description": "True when the customer may cancel the order in its current status."
                        },
                        "storage_code": {
                          "type": "string",
                          "nullable": true
                        },
                        "store_from": {
                          "type": "string"
                        },
                        "store_to": {
                          "type": "string"
                        },
                        "warehouse_id": {
                          "type": "integer"
                        },
                        "need_pickup": {
                          "type": "boolean"
                        },
                        "need_delivery": {
                          "type": "boolean"
                        },
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "description": {
                                "type": "string",
                                "nullable": true
                              },
                              "value": {
                                "type": "string",
                                "nullable": true
                              },
                              "weight": {
                                "type": "string",
                                "nullable": true
                              },
                              "weight_unit": {
                                "type": "integer",
                                "nullable": true,
                                "description": "1=g, 2=kg, 3=oz, 4=lb"
                              },
                              "length": {
                                "type": "string"
                              },
                              "width": {
                                "type": "string"
                              },
                              "height": {
                                "type": "string"
                              },
                              "dimension_unit": {
                                "type": "integer",
                                "description": "1=mm, 2=cm, 3=m, 4=in"
                              },
                              "packaging_id": {
                                "type": "integer",
                                "nullable": true
                              },
                              "packaging": {
                                "type": "object",
                                "nullable": true,
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "name": {
                                    "type": "string"
                                  }
                                }
                              },
                              "quantity": {
                                "type": "integer",
                                "example": 1
                              },
                              "received": {
                                "type": "boolean",
                                "description": "True once the warehouse has received this package."
                              }
                            }
                          }
                        },
                        "packages": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "description": {
                                "type": "string",
                                "nullable": true
                              },
                              "value": {
                                "type": "string",
                                "nullable": true
                              },
                              "weight": {
                                "type": "string",
                                "nullable": true
                              },
                              "weight_unit": {
                                "type": "integer",
                                "nullable": true,
                                "description": "1=g, 2=kg, 3=oz, 4=lb"
                              },
                              "length": {
                                "type": "string"
                              },
                              "width": {
                                "type": "string"
                              },
                              "height": {
                                "type": "string"
                              },
                              "dimension_unit": {
                                "type": "integer",
                                "description": "1=mm, 2=cm, 3=m, 4=in"
                              },
                              "packaging_id": {
                                "type": "integer",
                                "nullable": true
                              },
                              "packaging": {
                                "type": "object",
                                "nullable": true,
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "name": {
                                    "type": "string"
                                  }
                                }
                              },
                              "quantity": {
                                "type": "integer",
                                "example": 1
                              },
                              "received": {
                                "type": "boolean",
                                "description": "True once the warehouse has received this package."
                              }
                            }
                          }
                        },
                        "total_price": {
                          "type": "number",
                          "nullable": true
                        },
                        "currency": {
                          "type": "string",
                          "nullable": true
                        },
                        "created_at": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 1532,
                    "status": "partial received",
                    "can_edit": true,
                    "can_cancel": false,
                    "storage_code": "S7K2P9",
                    "store_from": "2026-10-01",
                    "store_to": "2026-10-31",
                    "warehouse_id": 12,
                    "need_pickup": false,
                    "need_delivery": false,
                    "items": [
                      {
                        "id": 901,
                        "description": "Books",
                        "value": "0",
                        "weight": "12",
                        "weight_unit": 2,
                        "length": "60",
                        "width": "40",
                        "height": "40",
                        "dimension_unit": 2,
                        "packaging_id": null,
                        "packaging": null,
                        "quantity": 1,
                        "received": true
                      },
                      {
                        "id": 902,
                        "description": "Lamp",
                        "value": "0",
                        "weight": "3",
                        "weight_unit": 2,
                        "length": "50",
                        "width": "30",
                        "height": "30",
                        "dimension_unit": 2,
                        "packaging_id": null,
                        "packaging": null,
                        "quantity": 1,
                        "received": false
                      }
                    ],
                    "total_price": 42.5,
                    "currency": "CAD",
                    "created_at": "2026-09-20 10:12:00"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "description": "Returns one storage order owned by the authenticated customer. `can_edit` and `can_cancel` tell the client whether PUT /v1/customer/storage-orders/{id} and POST /v1/customer/storage-orders/{id}/cancel will be accepted in the order's current status. Each package carries `received`: a received package is kept when the order is edited, so an edit must send only the packages whose `received` is false in `items`. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "x-route-name": "openapp.customer.storage-orders.id.get",
        "x-graphql": "customerStorageOrderShow",
        "x-capability": "orders.storage",
        "operationId": "customerStorageOrderShow"
      },
      "put": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerStorageOrderUpdate",
        "summary": "Update a storage order",
        "description": "Updates a storage order owned by the authenticated customer and recalculates its price. Allowed only while the order is pending payment, confirmed, waiting for pickup, awaiting dropoff or partially received. The warehouse and status cannot be changed; business_id, customer_id, warehouse_id and status are taken from the order and never read from the body. The body uses the same fields as the storage order create endpoint, with the storage period in store_from / store_to. form_data may be sent as {formId: {field: value}}. When the new price exceeds what was paid, the order returns to pending payment. Supplies (products {id: quantity}) are only the provider's own active supplies; any other product id is refused with 422 and errors.products. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "store_from",
                  "store_to"
                ],
                "additionalProperties": true,
                "properties": {
                  "store_from": {
                    "type": "string",
                    "format": "date"
                  },
                  "store_to": {
                    "type": "string",
                    "format": "date",
                    "description": "Must be after store_from"
                  },
                  "items": {
                    "type": "array",
                    "description": "Packages not yet received. Required (at least one) unless received_items is given.",
                    "items": {
                      "type": "object",
                      "required": [
                        "length",
                        "width",
                        "height",
                        "dimension_unit"
                      ],
                      "properties": {
                        "description": {
                          "type": "string",
                          "nullable": true
                        },
                        "packaging_id": {
                          "type": "integer",
                          "description": "Required unless the customer may use custom storage packages"
                        },
                        "value": {
                          "type": "number",
                          "minimum": 0,
                          "nullable": true
                        },
                        "weight": {
                          "type": "number",
                          "minimum": 0,
                          "nullable": true
                        },
                        "weight_unit": {
                          "type": "integer",
                          "nullable": true,
                          "description": "1=g, 2=kg, 3=oz, 4=lb"
                        },
                        "length": {
                          "type": "number",
                          "minimum": 0
                        },
                        "width": {
                          "type": "number",
                          "minimum": 0
                        },
                        "height": {
                          "type": "number",
                          "minimum": 0
                        },
                        "dimension_unit": {
                          "type": "integer",
                          "description": "1=mm, 2=cm, 3=m, 4=in"
                        }
                      }
                    }
                  },
                  "received_items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "description": "Packages already received; read-only, kept on the order"
                  },
                  "products": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "description": "Supplies as {productId: quantity}"
                  },
                  "need_pickup": {
                    "type": "boolean"
                  },
                  "pickup_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Required when need_pickup is true"
                  },
                  "pickup_start_time": {
                    "type": "string",
                    "description": "Required when need_pickup is true"
                  },
                  "pickup_end_time": {
                    "type": "string"
                  },
                  "pickup_address_1": {
                    "type": "string",
                    "description": "Required when need_pickup is true"
                  },
                  "pickup_city": {
                    "type": "string",
                    "description": "Required when need_pickup is true"
                  },
                  "pickup_province": {
                    "type": "string",
                    "description": "Required when need_pickup is true"
                  },
                  "pickup_country": {
                    "type": "string",
                    "description": "Required when need_pickup is true"
                  },
                  "pickup_postcode": {
                    "type": "string",
                    "description": "Required when need_pickup is true"
                  },
                  "pickup_channel_id": {
                    "type": "integer",
                    "description": "Storage channel setting id for the pickup"
                  },
                  "need_delivery": {
                    "type": "boolean"
                  },
                  "delivery_address_1": {
                    "type": "string",
                    "description": "Required when need_delivery is true"
                  },
                  "delivery_city": {
                    "type": "string",
                    "description": "Required when need_delivery is true"
                  },
                  "delivery_province": {
                    "type": "string",
                    "description": "Required when need_delivery is true"
                  },
                  "delivery_country": {
                    "type": "string",
                    "description": "Required when need_delivery is true"
                  },
                  "delivery_postcode": {
                    "type": "string",
                    "description": "Required when need_delivery is true"
                  },
                  "delivery_channel_id": {
                    "type": "integer",
                    "description": "Storage channel setting id for the delivery"
                  },
                  "need_supplies_delivery": {
                    "type": "boolean"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "form_data": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "object"
                    },
                    "description": "Custom form answers as {formId: {field: value}}"
                  }
                }
              },
              "example": {
                "store_from": "2026-10-01",
                "store_to": "2027-02-01",
                "items": [
                  {
                    "description": "Books",
                    "packaging_id": 3,
                    "length": 60,
                    "width": 40,
                    "height": 40,
                    "dimension_unit": 2,
                    "weight": 12,
                    "weight_unit": 2
                  }
                ],
                "need_pickup": false,
                "need_delivery": false,
                "notes": "Fragile"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Order updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Storage order updated",
                  "data": {
                    "id": 1024
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unexpected error while updating",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "..."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Storage order not found for this customer",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Storage order not found"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed, the price could not be calculated, or supplies are out of stock (the body then carries stock_shortages)",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "The store to must be a date after store from."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.storage-orders.id.put",
        "x-capability": "orders.storage",
        "x-graphql": "customerStorageOrderUpdate"
      }
    },
    "/app/v1/storage-orders/{id}/payment-info": {
      "get": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerStorageOrderPaymentInfo",
        "summary": "Get the payment options of a storage order",
        "description": "Returns the amounts due on a storage order owned by the authenticated customer, the customer's wallet balance and the payment options. When the order has a minimum payment that is not yet met and is below the remaining balance, three options are offered (minimum_payment, custom, full_balance); otherwise only remaining_balance. Amounts are strings with two decimals. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment information",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "order_id": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "total_price": {
                          "type": "string"
                        },
                        "original_price": {
                          "type": "string",
                          "description": "Price before promotion"
                        },
                        "paid_amount": {
                          "type": "string"
                        },
                        "remaining_balance": {
                          "type": "string"
                        },
                        "amount_due": {
                          "type": "string",
                          "description": "Same as remaining_balance"
                        },
                        "user_balance": {
                          "type": "string",
                          "description": "Customer wallet balance"
                        },
                        "has_sufficient_balance": {
                          "type": "boolean"
                        },
                        "shortfall": {
                          "description": "0 when the balance is sufficient, otherwise the missing amount as a string"
                        },
                        "allow_online_payment": {
                          "type": "integer"
                        },
                        "has_pickup_service": {
                          "type": "boolean"
                        },
                        "minimum_payment": {
                          "type": "string"
                        },
                        "has_previous_payment": {
                          "type": "boolean"
                        },
                        "payment_options": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "remaining_balance",
                                  "minimum_payment",
                                  "custom",
                                  "full_balance"
                                ]
                              },
                              "label": {
                                "type": "string"
                              },
                              "amount": {
                                "type": "number",
                                "nullable": true
                              },
                              "min_amount": {
                                "type": "number",
                                "description": "custom only"
                              },
                              "max_amount": {
                                "type": "number",
                                "description": "custom only"
                              },
                              "description": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "promotion": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "result": true,
                  "data": {
                    "order_id": 1024,
                    "currency": "CAD",
                    "total_price": "245.60",
                    "original_price": "245.60",
                    "paid_amount": "0.00",
                    "remaining_balance": "245.60",
                    "amount_due": "245.60",
                    "user_balance": "300.00",
                    "has_sufficient_balance": true,
                    "shortfall": 0,
                    "allow_online_payment": 1,
                    "has_pickup_service": true,
                    "minimum_payment": "65.60",
                    "has_previous_payment": false,
                    "payment_options": [
                      {
                        "type": "minimum_payment",
                        "label": "Pay Minimum Amount",
                        "amount": 65.6,
                        "description": "Pay the minimum amount to confirm your order"
                      },
                      {
                        "type": "custom",
                        "label": "Custom Amount",
                        "amount": null,
                        "min_amount": 65.6,
                        "max_amount": 245.6,
                        "description": "Enter a custom amount between minimum and total"
                      },
                      {
                        "type": "full_balance",
                        "label": "Pay Full Balance",
                        "amount": 245.6,
                        "description": "Pay the full amount"
                      }
                    ],
                    "promotion": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "The order is already fully paid",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "This order has already been fully paid."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "500": {
            "description": "Order not found in the customer's business, or an unexpected error",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "No query results for model [App\\StorageOrder]."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.storage-orders.id.payment-info.get",
        "x-capability": "orders.storage",
        "x-graphql": "customerStorageOrderPaymentInfo"
      }
    },
    "/app/v1/storage-orders/{id}/pay": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerStorageOrderPay",
        "summary": "Pay a storage order from the wallet balance",
        "description": "Pays a storage order owned by the authenticated customer from the customer's wallet balance. payment_type chooses the amount: minimum_payment (also pickup_only, deposit) pays the part of the minimum payment still missing, custom pays custom_amount (between the missing minimum, or 0.01, and the remaining balance), remaining_balance / full_balance (default) pays everything due. Meeting the minimum payment moves the order to waiting for pickup or awaiting dropoff and creates the pickup order when one is needed; full payment also creates the outbound order for reserved supplies. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_type": {
                    "type": "string",
                    "enum": [
                      "full_balance",
                      "remaining_balance",
                      "minimum_payment",
                      "pickup_only",
                      "deposit",
                      "custom"
                    ],
                    "default": "full_balance"
                  },
                  "custom_amount": {
                    "type": "number",
                    "description": "Required when payment_type is custom"
                  }
                }
              },
              "example": {
                "payment_type": "custom",
                "custom_amount": 100
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "new_balance": {
                      "type": "number",
                      "description": "Customer wallet balance after the payment"
                    },
                    "paid_amount": {
                      "type": "number",
                      "description": "Total paid on the order so far"
                    },
                    "charge_amount": {
                      "type": "number",
                      "description": "Amount charged by this payment"
                    },
                    "is_fully_paid": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "result": true,
                  "message": "Partial payment of 100.00 processed successfully. Remaining balance: 145.60",
                  "new_balance": 200.0,
                  "paid_amount": 100.0,
                  "charge_amount": 100.0,
                  "is_fully_paid": false
                }
              }
            }
          },
          "400": {
            "description": "The order is already fully paid, or the wallet balance is insufficient (the body then carries customer_balance)",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "Insufficient balance.",
                  "customer_balance": "20.00"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "422": {
            "description": "custom_amount is outside the allowed range",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "Invalid payment amount. Must be between 65.60 and 245.60"
                }
              }
            }
          },
          "500": {
            "description": "Order not found in the customer's business, or the payment failed",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "Error processing payment: ..."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.storage-orders.id.pay.post",
        "x-capability": "orders.storage",
        "x-graphql": "customerStorageOrderPay"
      }
    },
    "/app/v1/storage-orders/{id}/cancel": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerStorageOrderCancel",
        "summary": "Cancel a storage order",
        "description": "Cancels a storage order owned by the authenticated customer. Allowed only while the order is pending payment, confirmed, waiting for pickup or awaiting dropoff. The related pickup, delivery and supplies delivery orders are cancelled, reserved supplies are released, and the amount already paid is credited back to the customer's wallet balance. No request body. Needs orders.storage on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "Order cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string",
                          "example": "cancelled"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Storage order cancelled",
                  "data": {
                    "id": 1024,
                    "status": "cancelled"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Storage order not found for this customer",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Storage order not found"
                }
              }
            }
          },
          "422": {
            "description": "The cancellation was refused, for example because warehouse picking of the order's supplies has started",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Picking has already started for this order."
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error while cancelling",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "..."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.storage-orders.id.cancel.post",
        "x-capability": "orders.storage",
        "x-graphql": "customerStorageOrderCancel"
      }
    },
    "/app/v1/moving-orders/config": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Get the configuration bundle needed to render the customer 'create moving order' form",
        "description": "Returns the moving service packages (pricing plans) the customer picks from, plus the shared packaging catalog, supplies products, moving-date timeframes, unit definitions, surcharges, and dynamic form bindings. Moving orders do not use warehouses — the customer provides origin/destination addresses directly. Requires an authenticated customer account. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Config bundle",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "moving_packages": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "display_name": {
                                "type": "object",
                                "description": "Locale map"
                              },
                              "description": {
                                "type": "object",
                                "description": "Locale map"
                              },
                              "is_default": {
                                "type": "boolean"
                              },
                              "display_order": {
                                "type": "integer"
                              },
                              "pricing_type": {
                                "type": "integer"
                              },
                              "base_price": {
                                "type": "number",
                                "nullable": true
                              },
                              "hourly_rate": {
                                "type": "number",
                                "nullable": true
                              },
                              "min_hours": {
                                "type": "number",
                                "nullable": true
                              },
                              "min_charge": {
                                "type": "number",
                                "nullable": true
                              },
                              "prepay_ratio": {
                                "type": "number",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "packagings": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "display_names": {
                                "type": "object",
                                "description": "Packaging name per language code (en, chs, cht, fr…) as the client entered it; empty languages are left out. Show the entry for the app's language, falling back to `name`.",
                                "example": {
                                  "en": "A1. Carry-on luggage",
                                  "chs": "A1. 手提行李箱"
                                }
                              }
                            }
                          }
                        },
                        "products": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "moving_timeframes": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "dimension_units": {
                          "type": "object"
                        },
                        "weight_units": {
                          "type": "object"
                        },
                        "default_dimension_unit": {
                          "type": "integer",
                          "nullable": true
                        },
                        "default_weight_unit": {
                          "type": "integer",
                          "nullable": true
                        },
                        "surcharges": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "form_bindings": {
                          "type": "array",
                          "description": "Custom forms bound to moving orders, in the same shape as the storage and shipping config. Answers go back on create as form_data {form_id: {field code: value}}.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "form_id": {
                                "type": "integer"
                              },
                              "form_code": {
                                "type": "string"
                              },
                              "form_name": {
                                "type": "string"
                              },
                              "is_required": {
                                "type": "boolean"
                              },
                              "remember_answers": {
                                "type": "boolean"
                              },
                              "sort_order": {
                                "type": "integer"
                              },
                              "fields": {
                                "type": "array",
                                "items": {
                                  "$ref": "#/components/schemas/CustomerOrderFormField"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.moving-orders.config.get",
        "x-graphql": "customerMovingOrderConfig",
        "x-capability": "orders.moving",
        "operationId": "customerMovingOrderConfig"
      }
    },
    "/app/v1/moving-orders/calculate-price": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerMovingOrderCalculatePrice",
        "summary": "Calculate the price of a moving order",
        "description": "Estimate the price of a moving order. Writes nothing. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "warehouse_id",
                  "start_date",
                  "end_date"
                ],
                "properties": {
                  "warehouse_id": {
                    "type": "integer"
                  },
                  "start_date": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-10-01"
                  },
                  "end_date": {
                    "type": "string",
                    "format": "date",
                    "example": "2027-01-01"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "packaging_id": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Packaging id from the config endpoint"
                        },
                        "qty": {
                          "type": "integer",
                          "example": 1,
                          "default": 1
                        },
                        "length": {
                          "type": "number"
                        },
                        "width": {
                          "type": "number"
                        },
                        "height": {
                          "type": "number"
                        },
                        "dimension_unit": {
                          "type": "integer",
                          "description": "1=mm, 2=cm, 3=m, 4=in"
                        },
                        "weight": {
                          "type": "number",
                          "nullable": true
                        },
                        "weight_unit": {
                          "type": "integer",
                          "nullable": true,
                          "description": "1=g, 2=kg, 3=oz, 4=lb"
                        }
                      }
                    },
                    "description": "Packages to store; may be empty"
                  },
                  "products": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Supplies to buy, as {productId: quantity}; quantities of 0 are ignored"
                  },
                  "need_pickup": {
                    "type": "boolean",
                    "default": false
                  },
                  "pickup_postcode": {
                    "type": "string"
                  },
                  "pickup_country": {
                    "type": "string"
                  },
                  "pickup_channel_id": {
                    "type": "integer",
                    "description": "Storage channel setting id for the pickup"
                  },
                  "need_delivery": {
                    "type": "boolean",
                    "default": false
                  },
                  "delivery_postcode": {
                    "type": "string"
                  },
                  "delivery_country": {
                    "type": "string"
                  },
                  "delivery_channel_id": {
                    "type": "integer",
                    "description": "Storage channel setting id for the delivery"
                  },
                  "need_supplies_delivery": {
                    "type": "boolean",
                    "default": false
                  },
                  "surcharges": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "description": "Surcharge selections"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "selected_promotion_id": {
                    "type": "integer",
                    "description": "Automatic promotion to apply when several match"
                  },
                  "order_id": {
                    "type": "integer",
                    "description": "When repricing an existing order: its id. Received packages of that order are added to the price and the order's own promotion usage is not counted against limits."
                  }
                }
              },
              "example": {
                "warehouse_id": 7,
                "start_date": "2026-10-01",
                "end_date": "2027-01-01",
                "items": [
                  {
                    "packaging_id": 3,
                    "qty": 2,
                    "length": 60,
                    "width": 40,
                    "height": 40,
                    "dimension_unit": 2,
                    "weight": 12,
                    "weight_unit": 2
                  }
                ],
                "need_pickup": true,
                "pickup_postcode": "M5V2H1",
                "pickup_country": "CA",
                "pickup_channel_id": 4
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Price calculated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "price": {
                      "type": "object",
                      "additionalProperties": true,
                      "properties": {
                        "shipping_price": {
                          "type": "number",
                          "description": "Total including tax"
                        },
                        "total_price": {
                          "type": "string",
                          "example": "245.60"
                        },
                        "currency": {
                          "type": "string",
                          "example": "CAD"
                        },
                        "storage": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "pickup": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "delivery": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "products": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "supplies_delivery": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "surcharges": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      }
                    },
                    "promotion": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Present only when a promotion applies"
                    },
                    "available_promotions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "description": "Present only when automatic promotions match"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "price": {
                    "shipping_price": 245.6,
                    "total_price": "245.60",
                    "currency": "CAD",
                    "storage": {
                      "result": true,
                      "shipping_price": 180.0,
                      "currency": "CAD"
                    },
                    "pickup": {
                      "result": true,
                      "shipping_price": 65.6,
                      "currency": "CAD"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing warehouse_id, start_date or end_date, or the price could not be calculated",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "message": "Missing required fields"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Warehouse not found",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "message": "Warehouse not found"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error while calculating",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "message": "Error calculating price: ..."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.moving-orders.calculate-price.post",
        "x-graphql": "customerMovingOrderCalculatePrice",
        "x-capability": "orders.moving"
      }
    },
    "/app/v1/moving-orders": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List the authenticated customer's moving orders",
        "description": "Paginated list; mirrors admin MovingOrderController::index filter/sort semantics via MovingOrderService::getMovingOrders, scoped to the authenticated customer. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "moving_date_from",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "moving_date_to",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "created_at_from",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "created_at_to",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "sort_by",
            "schema": {
              "type": "string",
              "enum": [
                "created_desc",
                "date_asc"
              ],
              "default": "created_desc"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.moving-orders.get",
        "x-graphql": "customerMovingOrders",
        "x-capability": "orders.moving",
        "operationId": "customerMovingOrders"
      },
      "post": {
        "tags": [
          "Customer Moving Orders"
        ],
        "operationId": "customerMovingOrderCreate",
        "summary": "Create a moving order",
        "description": "Creates a moving order for the authenticated customer. Same fields as the moving order form; business_id and customer_id come from the authentication and are never read from the body. Supports the OPTIONAL Idempotency-Key header. Supplies (products {id: quantity}) are only the provider's own active supplies; any other product id is refused with 422 and errors.products. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. A key derived from your own stable ids. A repeated key with the same body replays the first 2xx answer (body replayed: true, header Idempotency-Replayed: true); the same key with a different body is refused 409 IDEMPOTENCY_CONFLICT; a non-2xx outcome releases the key so the request may be corrected and retried."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "The moving order form fields: addresses, date, resources, channel fields, and per-form form_data. The authoritative field list is the moving order form; unknown fields are ignored.",
                "properties": {
                  "quote_token": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Optional. The token of the public quote (/quotes) this order comes from. Once the order is created the quote records it; an unknown or already converted token is ignored and never fails the order.",
                    "example": "k3v9q2m8x1c7b5n4z6a0s2d8f1g3h5j7k9l2p4o6"
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created. The body carries result and the created order.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present only when the response is an Idempotency-Key replay of a previously stored outcome.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "replayed": {
                      "type": "boolean",
                      "description": "Present only on an Idempotency-Key replay"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "409": {
            "description": "Idempotency conflict: the key was already used with a different body (IDEMPOTENCY_CONFLICT), or the original request is still processing (IDEMPOTENCY_IN_PROGRESS, with Retry-After: 1).",
            "headers": {
              "Retry-After": {
                "description": "Present only on the IDEMPOTENCY_IN_PROGRESS answer: retry after this many seconds.",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.moving-orders.post",
        "x-capability": "orders.moving",
        "x-graphql": "customerMovingOrderCreate"
      }
    },
    "/app/v1/moving-orders/{id}": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Get the detail of one moving order owned by the authenticated customer",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Moving order detail. Additive: data.can_edit (the customer may still change it: their own order while pending payment) and data.can_cancel (pending payment, confirmed or scheduled), the rules the update and cancel endpoints enforce, as storage orders already answer."
          },
          "404": {
            "description": "Not found"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.moving-orders.id.get",
        "x-graphql": "customerMovingOrderShow",
        "x-capability": "orders.moving",
        "description": "Needs orders.moving on the token; answered exactly as the internal customer route.",
        "operationId": "customerMovingOrderShow"
      },
      "put": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerMovingOrderUpdate",
        "summary": "Update a moving order",
        "description": "Updates a moving order owned by the authenticated customer while it is pending payment. The body has the same shape as the create endpoint (moving date and time, origin and destination addresses, items, products {id: quantity}, surcharges, form_data {form id: answers}, moving_time_slot_id); the price is always recalculated and promotions are re-evaluated. A date without capacity is refused with 422; supplies that are not the provider's own active products are refused with 422 and errors.products; a shortage of supplies stock is refused with 422 and stock_shortages; a validation failure answers 500 with the message. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Moving order id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "required": [
                  "moving_date",
                  "origin_address_1",
                  "origin_city",
                  "origin_province",
                  "origin_country",
                  "origin_postcode",
                  "destination_address_1",
                  "destination_city",
                  "destination_province",
                  "destination_country",
                  "destination_postcode"
                ],
                "properties": {
                  "moving_date": {
                    "type": "string"
                  },
                  "moving_start_time": {
                    "type": "string"
                  },
                  "moving_end_time": {
                    "type": "string"
                  },
                  "origin_address_1": {
                    "type": "string"
                  },
                  "origin_address_2": {
                    "type": "string"
                  },
                  "origin_city": {
                    "type": "string"
                  },
                  "origin_province": {
                    "type": "string"
                  },
                  "origin_country": {
                    "type": "string"
                  },
                  "origin_postcode": {
                    "type": "string"
                  },
                  "destination_address_1": {
                    "type": "string"
                  },
                  "destination_address_2": {
                    "type": "string"
                  },
                  "destination_city": {
                    "type": "string"
                  },
                  "destination_province": {
                    "type": "string"
                  },
                  "destination_country": {
                    "type": "string"
                  },
                  "destination_postcode": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "moving_package_id": {
                    "type": "integer"
                  },
                  "moving_time_slot_id": {
                    "type": "integer"
                  },
                  "estimated_hours": {
                    "type": "number"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  },
                  "products": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer"
                    }
                  },
                  "surcharges": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  },
                  "form_data": {
                    "type": "object"
                  }
                }
              },
              "example": {
                "moving_date": "2026-11-01",
                "origin_address_1": "1 Main St",
                "origin_city": "Vancouver",
                "origin_province": "BC",
                "origin_country": "CA",
                "origin_postcode": "V6B1A1",
                "destination_address_1": "2 Side St",
                "destination_city": "Burnaby",
                "destination_province": "BC",
                "destination_country": "CA",
                "destination_postcode": "V5K0A1"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "redirect_url": {
                      "type": "string"
                    },
                    "result": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Moving order updated successfully",
                  "redirect_url": "https://admin.superroute.ca/movingorder/123",
                  "result": true
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not editable"
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Moving order not found"
                }
              }
            }
          },
          "422": {
            "description": "Refused (capacity, supplies or stock)"
          },
          "500": {
            "description": "Validation failed; message names the field"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.moving-orders.id.put",
        "x-graphql": "customerMovingOrderUpdate",
        "x-capability": "orders.moving"
      }
    },
    "/app/v1/moving-orders/{id}/payment-info": {
      "get": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerMovingOrderPaymentInfo",
        "summary": "Get the payment options of a moving order",
        "description": "What is paid and what is left to pay on a moving order. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment information",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "order_id": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "total_price": {
                          "type": "string"
                        },
                        "original_price": {
                          "type": "string",
                          "description": "Price before promotion"
                        },
                        "paid_amount": {
                          "type": "string"
                        },
                        "remaining_balance": {
                          "type": "string"
                        },
                        "amount_due": {
                          "type": "string",
                          "description": "Same as remaining_balance"
                        },
                        "user_balance": {
                          "type": "string",
                          "description": "Customer wallet balance"
                        },
                        "has_sufficient_balance": {
                          "type": "boolean"
                        },
                        "shortfall": {
                          "description": "0 when the balance is sufficient, otherwise the missing amount as a string"
                        },
                        "allow_online_payment": {
                          "type": "integer"
                        },
                        "has_pickup_service": {
                          "type": "boolean"
                        },
                        "minimum_payment": {
                          "type": "string"
                        },
                        "has_previous_payment": {
                          "type": "boolean"
                        },
                        "payment_options": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "remaining_balance",
                                  "minimum_payment",
                                  "custom",
                                  "full_balance"
                                ]
                              },
                              "label": {
                                "type": "string"
                              },
                              "amount": {
                                "type": "number",
                                "nullable": true
                              },
                              "min_amount": {
                                "type": "number",
                                "description": "custom only"
                              },
                              "max_amount": {
                                "type": "number",
                                "description": "custom only"
                              },
                              "description": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "promotion": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "result": true,
                  "data": {
                    "order_id": 1024,
                    "currency": "CAD",
                    "total_price": "245.60",
                    "original_price": "245.60",
                    "paid_amount": "0.00",
                    "remaining_balance": "245.60",
                    "amount_due": "245.60",
                    "user_balance": "300.00",
                    "has_sufficient_balance": true,
                    "shortfall": 0,
                    "allow_online_payment": 1,
                    "has_pickup_service": true,
                    "minimum_payment": "65.60",
                    "has_previous_payment": false,
                    "payment_options": [
                      {
                        "type": "minimum_payment",
                        "label": "Pay Minimum Amount",
                        "amount": 65.6,
                        "description": "Pay the minimum amount to confirm your order"
                      },
                      {
                        "type": "custom",
                        "label": "Custom Amount",
                        "amount": null,
                        "min_amount": 65.6,
                        "max_amount": 245.6,
                        "description": "Enter a custom amount between minimum and total"
                      },
                      {
                        "type": "full_balance",
                        "label": "Pay Full Balance",
                        "amount": 245.6,
                        "description": "Pay the full amount"
                      }
                    ],
                    "promotion": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "The order is already fully paid",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "This order has already been fully paid."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "500": {
            "description": "Order not found in the customer's business, or an unexpected error",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "No query results for model [App\\StorageOrder]."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.moving-orders.id.payment-info.get",
        "x-graphql": "customerMovingOrderPaymentInfo",
        "x-capability": "orders.moving"
      }
    },
    "/app/v1/moving-orders/{id}/pay": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerMovingOrderPay",
        "summary": "Pay a moving order from the wallet balance",
        "description": "Pay a moving order. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_type": {
                    "type": "string",
                    "enum": [
                      "full_balance",
                      "remaining_balance",
                      "minimum_payment",
                      "pickup_only",
                      "deposit",
                      "custom"
                    ],
                    "default": "full_balance"
                  },
                  "custom_amount": {
                    "type": "number",
                    "description": "Required when payment_type is custom"
                  }
                }
              },
              "example": {
                "payment_type": "custom",
                "custom_amount": 100
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "new_balance": {
                      "type": "number",
                      "description": "Customer wallet balance after the payment"
                    },
                    "paid_amount": {
                      "type": "number",
                      "description": "Total paid on the order so far"
                    },
                    "charge_amount": {
                      "type": "number",
                      "description": "Amount charged by this payment"
                    },
                    "is_fully_paid": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "result": true,
                  "message": "Partial payment of 100.00 processed successfully. Remaining balance: 145.60",
                  "new_balance": 200.0,
                  "paid_amount": 100.0,
                  "charge_amount": 100.0,
                  "is_fully_paid": false
                }
              }
            }
          },
          "400": {
            "description": "The order is already fully paid, or the wallet balance is insufficient (the body then carries customer_balance)",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "Insufficient balance.",
                  "customer_balance": "20.00"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "422": {
            "description": "custom_amount is outside the allowed range",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "Invalid payment amount. Must be between 65.60 and 245.60"
                }
              }
            }
          },
          "500": {
            "description": "Order not found in the customer's business, or the payment failed",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "result": false,
                  "message": "Error processing payment: ..."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.moving-orders.id.pay.post",
        "x-graphql": "customerMovingOrderPay",
        "x-capability": "orders.moving"
      }
    },
    "/app/v1/moving-orders/{id}/cancel": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerMovingOrderCancel",
        "summary": "Cancel a moving order",
        "description": "Cancel a moving order in a cancellable status. Needs orders.moving on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "Order cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string",
                          "example": "cancelled"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Moving order cancelled",
                  "data": {
                    "id": 1024,
                    "status": "cancelled"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Moving order not found for this customer",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Moving order not found"
                }
              }
            }
          },
          "422": {
            "description": "The cancellation was refused, for example because warehouse picking of the order's supplies has started",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Picking has already started for this order."
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error while cancelling",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "..."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.moving-orders.id.cancel.post",
        "x-graphql": "customerMovingOrderCancel",
        "x-capability": "orders.moving"
      }
    },
    "/app/v1/order-announcements": {
      "get": {
        "summary": "GET /app/v1/order-announcements",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.order-announcements.get",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerOrderAnnouncementsGet"
      }
    },
    "/app/v1/order-announcements/confirm": {
      "post": {
        "summary": "POST /app/v1/order-announcements/confirm",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.order-announcements.confirm.post",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Answered exactly as the internal customer route.",
        "operationId": "customerOrderAnnouncementsConfirmPost"
      }
    },
    "/app/v1/shipping-orders/services": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List shipping services available to the authenticated customer",
        "description": "Returns a lightweight list of shipping services the customer is authorized to use, derived from the customer_shipping_service assignment table. Used as step 1 of the two-step create-order flow; once the customer picks a service, fetch /v1/customer/shipping-orders/services/{serviceCode}/config for the full details. Customers with no explicit service assignment see an empty list. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Services list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "services": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "service_code": {
                                "type": "string"
                              },
                              "name": {
                                "type": "object",
                                "description": "Locale map"
                              },
                              "offer_pickup": {
                                "type": "boolean"
                              },
                              "allow_warehouse_delivery": {
                                "type": "boolean"
                              },
                              "support_multi_package": {
                                "type": "boolean"
                              },
                              "allow_special_requirements": {
                                "type": "boolean"
                              },
                              "allow_purchase_supplies": {
                                "type": "boolean"
                              },
                              "send_confirmation_email": {
                                "type": "boolean"
                              },
                              "warehouses": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "integer"
                                    },
                                    "name": {
                                      "type": "string"
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "services": [
                      {
                        "id": 12,
                        "service_code": "intl_express",
                        "name": {
                          "en": "International Express",
                          "chs": "国际快递"
                        },
                        "offer_pickup": true,
                        "allow_warehouse_delivery": true,
                        "support_multi_package": true,
                        "allow_special_requirements": false,
                        "allow_purchase_supplies": true,
                        "send_confirmation_email": true,
                        "warehouses": [
                          {
                            "id": 5,
                            "name": "Toronto Hub"
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.services.get",
        "x-graphql": "customerShippingOrderServices",
        "x-capability": "orders.shipping",
        "operationId": "customerShippingOrderServices"
      }
    },
    "/app/v1/shipping-orders/services/{serviceCode}/config": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Get the per-service configuration bundle needed to render the 'create shipping order' form",
        "description": "Returns the full config for one shipping service: that service's warehouses (with full address fields), surcharges (drawn from the service's surcharge groups), plus the shared packaging catalog, supplies products (only when allow_purchase_supplies), unit definitions, and dynamic form bindings. Call this after the user picks a service from /v1/customer/shipping-orders/services. Returns 403 if the customer is not authorized for the given service, 404 if it does not exist. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "serviceCode",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The shipping service service_code (unique per business)"
          }
        ],
        "responses": {
          "200": {
            "description": "Config bundle",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "service": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "service_code": {
                              "type": "string"
                            },
                            "name": {
                              "type": "object"
                            },
                            "offer_pickup": {
                              "type": "boolean"
                            },
                            "allow_warehouse_delivery": {
                              "type": "boolean"
                            },
                            "support_multi_package": {
                              "type": "boolean"
                            },
                            "allow_special_requirements": {
                              "type": "boolean"
                            },
                            "allow_purchase_supplies": {
                              "type": "boolean"
                            },
                            "send_confirmation_email": {
                              "type": "boolean"
                            }
                          }
                        },
                        "warehouses": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "address": {
                                "type": "string"
                              },
                              "address_1": {
                                "type": "string"
                              },
                              "address_2": {
                                "type": "string"
                              },
                              "city": {
                                "type": "string"
                              },
                              "province": {
                                "type": "string"
                              },
                              "country": {
                                "type": "string"
                              },
                              "postcode": {
                                "type": "string"
                              },
                              "telephone": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "packagings": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "display_names": {
                                "type": "object",
                                "description": "Packaging name per language code (en, chs, cht, fr…) as the client entered it; empty languages are left out. Show the entry for the app's language, falling back to `name`.",
                                "example": {
                                  "en": "A1. Carry-on luggage",
                                  "chs": "A1. 手提行李箱"
                                }
                              }
                            }
                          }
                        },
                        "products": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          },
                          "description": "Empty unless the service has allow_purchase_supplies=true"
                        },
                        "surcharges": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "dimension_units": {
                          "type": "object"
                        },
                        "weight_units": {
                          "type": "object"
                        },
                        "default_dimension_unit": {
                          "type": "integer",
                          "nullable": true,
                          "description": "The unit a new order form opens with: the client's customer default (Unit Settings) when set, otherwise the customer's own display unit."
                        },
                        "default_weight_unit": {
                          "type": "integer",
                          "nullable": true,
                          "description": "The unit a new order form opens with: the client's customer default (Unit Settings) when set, otherwise the customer's own display unit."
                        },
                        "form_bindings": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "remember_answers": {
                                "type": "boolean",
                                "description": "The customer may keep this form's answers on their account (see /v1/customer/saved-form-answers)."
                              }
                            }
                          }
                        },
                        "saved_form_answers": {
                          "type": "object",
                          "description": "Answers the customer keeps on their account, keyed by form id, then field code → string or list of strings. Only forms whose binding has `remember_answers` on are included. Prefill a new order's form fields from it.",
                          "additionalProperties": {
                            "type": "object"
                          },
                          "example": {
                            "3": {
                              "wechat": "wx_alice"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Service not found",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Shipping service not found."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.services.serviceCode.config.get",
        "x-graphql": "customerShippingOrderServiceConfig",
        "x-capability": "orders.shipping",
        "operationId": "customerShippingOrderServiceConfig"
      }
    },
    "/app/v1/shipping-orders/services/{serviceCode}/estimate-price": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerShippingOrderEstimatePrice",
        "summary": "Estimate the price of a shipping order on a service",
        "description": "Calculates the price of a shipping order on the named service without saving anything, then evaluates promotions: a valid coupon_code is applied first; otherwise a single matching automatic promotion is applied, or the one named by selected_promotion_id when several match. products are honoured only when the service allows buying supplies. The service must be active and available to the customer.\n\nThe estimate also carries `unpriced_items` (fees that could not be priced automatically), `refused` (true when the service refuses such a shipment) and `refusal_message`; an order placed for a refused estimate is answered with HTTP 422, code `unpriced_refused`. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "serviceCode",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Shipping service code, as returned by the services list"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "origin_type": {
                    "type": "string",
                    "enum": [
                      "warehouse",
                      "pickup"
                    ],
                    "default": "warehouse"
                  },
                  "warehouse_id": {
                    "type": "integer",
                    "description": "Drop-off warehouse when origin_type is warehouse"
                  },
                  "pickup_postcode": {
                    "type": "string"
                  },
                  "pickup_country": {
                    "type": "string"
                  },
                  "delivery_postcode": {
                    "type": "string",
                    "description": "Needed for a price"
                  },
                  "delivery_country": {
                    "type": "string",
                    "description": "Needed for a price"
                  },
                  "packages": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "weight": {
                          "type": "number"
                        },
                        "length": {
                          "type": "number"
                        },
                        "width": {
                          "type": "number"
                        },
                        "height": {
                          "type": "number"
                        },
                        "weight_unit": {
                          "type": "integer"
                        },
                        "dimension_unit": {
                          "type": "integer"
                        },
                        "quantity": {
                          "type": "integer",
                          "default": 1
                        }
                      }
                    }
                  },
                  "has_special_requirements": {
                    "type": "boolean",
                    "default": false
                  },
                  "surcharges": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "description": "Surcharge selections"
                  },
                  "products": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Supplies as {productId: quantity}"
                  },
                  "need_supplies_delivery": {
                    "type": "boolean"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "selected_promotion_id": {
                    "type": "integer"
                  }
                }
              },
              "example": {
                "origin_type": "warehouse",
                "warehouse_id": 7,
                "delivery_postcode": "V6B1A1",
                "delivery_country": "CA",
                "packages": [
                  {
                    "weight": 2.5,
                    "length": 30,
                    "width": 20,
                    "height": 15,
                    "weight_unit": 2,
                    "dimension_unit": 2,
                    "quantity": 1
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Price estimate",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true,
                      "properties": {
                        "needs_manual_quote": {
                          "type": "boolean"
                        },
                        "manual_quote_reasons": {
                          "type": "array",
                          "items": {}
                        },
                        "shipping_fee": {
                          "type": "number",
                          "nullable": true
                        },
                        "shipping_fee_total": {
                          "type": "number",
                          "nullable": true
                        },
                        "fuel_surcharge": {
                          "type": "number"
                        },
                        "handling_fee": {
                          "type": "number"
                        },
                        "shipping_fee_error": {
                          "type": "string",
                          "nullable": true
                        },
                        "pickup_fee": {
                          "type": "number",
                          "nullable": true
                        },
                        "pickup_fee_error": {
                          "type": "string",
                          "nullable": true
                        },
                        "surcharges": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "surcharges_total": {
                          "type": "number"
                        },
                        "sub_total": {
                          "type": "number"
                        },
                        "tax": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true
                        },
                        "total": {
                          "type": "number",
                          "nullable": true
                        },
                        "currency": {
                          "type": "string",
                          "nullable": true
                        },
                        "all_fees_calculated": {
                          "type": "boolean"
                        },
                        "fee_items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "has_items_needing_quote": {
                          "type": "boolean"
                        },
                        "unpriced_items": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "refused": {
                          "type": "boolean"
                        },
                        "refusal_message": {
                          "type": "string",
                          "nullable": true
                        },
                        "promotion": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Present only when a promotion applies"
                        },
                        "available_promotions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "description": "Present only when automatic promotions match"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "needs_manual_quote": false,
                    "manual_quote_reasons": [],
                    "shipping_fee": 18.5,
                    "shipping_fee_total": 20.35,
                    "fuel_surcharge": 1.85,
                    "handling_fee": 0,
                    "shipping_fee_error": null,
                    "pickup_fee": null,
                    "pickup_fee_error": null,
                    "surcharges": [],
                    "surcharges_total": 0,
                    "sub_total": 20.35,
                    "tax": {
                      "total_tax": 2.65
                    },
                    "total": 23.0,
                    "currency": "CAD",
                    "all_fees_calculated": true,
                    "fee_items": [],
                    "has_items_needing_quote": false,
                    "unpriced_items": [],
                    "refused": false,
                    "refusal_message": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "No active shipping service with this code",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Shipping service not found."
                }
              }
            }
          },
          "500": {
            "description": "The price could not be calculated",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Failed to calculate price."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.services.serviceCode.estimate-price.post",
        "x-capability": "orders.shipping",
        "x-graphql": "customerShippingOrderEstimatePrice"
      }
    },
    "/app/v1/shipping-orders/services/{serviceCode}/orders": {
      "post": {
        "tags": [
          "Customer Shipping Orders"
        ],
        "operationId": "customerShippingOrderCreate",
        "summary": "Create a shipping order on a service",
        "description": "Creates a shipping order on the named shipping service for the authenticated customer. The service must be active and available to the caller. Supports the OPTIONAL Idempotency-Key header; the serviceCode path parameter joins the idempotency fingerprint, so the same key on a different service is a conflict, never a replay.\n\nWhen the shipping service is set to refuse shipments it cannot price automatically (the default) and the price plan has no price for the destination, or the pickup has no price for the pickup address, the request is refused with HTTP 422, code `unpriced_refused` and a message in the caller's language; nothing is created. A service set to take such shipments for a manual quote creates the order awaiting a quote, as before. Supplies (products {id: quantity}) are only the provider's own active supplies; any other product id is refused with 422 and errors.products. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "serviceCode",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. A key derived from your own stable ids. A repeated key with the same body replays the first 2xx answer (body replayed: true, header Idempotency-Replayed: true); the same key with a different body is refused 409 IDEMPOTENCY_CONFLICT; a non-2xx outcome releases the key so the request may be corrected and retried."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "The shipping order fields for the service: consignee address and contact, packages with stated units, pickup/delivery options. The authoritative field list is the shipping order form of the service; unknown fields are ignored.",
                "properties": {
                  "quote_token": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Optional. The token of the public quote (/quotes) this order comes from. Once the order is created the quote records it; an unknown or already converted token is ignored and never fails the order.",
                    "example": "k3v9q2m8x1c7b5n4z6a0s2d8f1g3h5j7k9l2p4o6"
                  },
                  "form_data": {
                    "type": "object",
                    "description": "Optional. Answers to the client's custom forms for shipping orders (form_bindings of the service config), keyed by form id, then field code. A form bound as required must be answered by the rules of its fields; every answered form is kept with the order. Same shape as the storage and moving create.",
                    "additionalProperties": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "example": {
                      "3": {
                        "wechat": "wx_alice"
                      }
                    }
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created. The body carries result and the created order.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present only when the response is an Idempotency-Key replay of a previously stored outcome.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "replayed": {
                      "type": "boolean",
                      "description": "Present only on an Idempotency-Key replay"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "409": {
            "description": "Idempotency conflict: the key was already used with a different body (IDEMPOTENCY_CONFLICT), or the original request is still processing (IDEMPOTENCY_IN_PROGRESS, with Retry-After: 1).",
            "headers": {
              "Retry-After": {
                "description": "Present only on the IDEMPOTENCY_IN_PROGRESS answer: retry after this many seconds.",
                "schema": {
                  "type": "string",
                  "example": "1"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed Also returned with code `unpriced_refused` when the shipping service refuses a shipment it cannot price. A required custom form left unanswered (or answered outside its options) answers {result: false, message, errors: {\"form_data_<form id>.<field code>\": message}} before anything is written.",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "success": false,
                  "message": "Please correct the errors below.",
                  "errors": {
                    "form_data_3.wechat": "WeChat is required."
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.services.serviceCode.orders.post",
        "x-capability": "orders.shipping",
        "x-graphql": "customerShippingOrderCreate"
      },
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List the authenticated customer's shipping orders under one service",
        "description": "Paginated list scoped to the customer + service. 403 if the customer is not authorized for the service; 404 if the service does not exist. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "serviceCode",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "id",
            "schema": {
              "type": "string"
            },
            "description": "Matches order id, tracking_number or reference_number"
          },
          {
            "in": "query",
            "name": "created_at_from",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "created_at_to",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "sort_by",
            "schema": {
              "type": "string",
              "enum": [
                "created_desc",
                "created_asc"
              ],
              "default": "created_desc"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Service not found"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.services.serviceCode.orders.get",
        "x-graphql": "customerShippingOrders",
        "x-capability": "orders.shipping",
        "operationId": "customerShippingOrders"
      }
    },
    "/app/v1/shipping-orders/{id}": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Get the detail of one shipping order owned by the authenticated customer",
        "description": "The order id alone identifies the service; the customer's service access is enforced via the customer_shipping_service assignment (returns 403 if the order's service is not granted to this customer). Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Shipping order detail"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Order not found"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.id.get",
        "x-graphql": "customerShippingOrderShow",
        "x-capability": "orders.shipping",
        "operationId": "customerShippingOrderShow"
      },
      "put": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerShippingOrderUpdate",
        "summary": "Update a shipping order",
        "description": "Updates a shipping order owned by the authenticated customer. Allowed only while the order is pending. The body has the same shape as the create endpoint; packages and special requirements are replaced, the price is recalculated and promotions are re-evaluated (coupon_code from the body, or the order's current coupon when omitted). When the service cannot price the edited order and refuses unpriced shipments, the update is refused with HTTP 422, code `unpriced_refused`, and nothing is changed. Supplies (products {id: quantity}) are only the provider's own active supplies; any other product id is refused with 422 and errors.products. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "delivery_name",
                  "delivery_telephone",
                  "delivery_address_1",
                  "delivery_postcode",
                  "delivery_city",
                  "delivery_province",
                  "delivery_country",
                  "package"
                ],
                "additionalProperties": true,
                "properties": {
                  "origin_type": {
                    "type": "string",
                    "enum": [
                      "pickup",
                      "warehouse"
                    ],
                    "description": "Defaults to the order's current origin type"
                  },
                  "warehouse_id": {
                    "type": "integer",
                    "description": "Required when origin_type is warehouse"
                  },
                  "pickup_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Required when origin_type is pickup"
                  },
                  "pickup_telephone": {
                    "type": "string",
                    "maxLength": 50,
                    "description": "Required when origin_type is pickup"
                  },
                  "pickup_email": {
                    "type": "string"
                  },
                  "pickup_address_1": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Required when origin_type is pickup"
                  },
                  "pickup_address_2": {
                    "type": "string"
                  },
                  "pickup_postcode": {
                    "type": "string",
                    "maxLength": 20,
                    "description": "Required when origin_type is pickup"
                  },
                  "pickup_city": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Required when origin_type is pickup"
                  },
                  "pickup_province": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Required when origin_type is pickup"
                  },
                  "pickup_country": {
                    "type": "string",
                    "maxLength": 10,
                    "description": "Required when origin_type is pickup"
                  },
                  "delivery_name": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "delivery_telephone": {
                    "type": "string",
                    "maxLength": 50
                  },
                  "delivery_email": {
                    "type": "string"
                  },
                  "delivery_address_1": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "delivery_address_2": {
                    "type": "string"
                  },
                  "delivery_postcode": {
                    "type": "string",
                    "maxLength": 20
                  },
                  "delivery_city": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "delivery_province": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "delivery_country": {
                    "type": "string",
                    "maxLength": 10
                  },
                  "package": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "object",
                      "properties": {
                        "weight": {
                          "type": "number"
                        },
                        "length": {
                          "type": "number"
                        },
                        "width": {
                          "type": "number"
                        },
                        "height": {
                          "type": "number"
                        },
                        "weight_unit": {
                          "type": "integer",
                          "default": 2
                        },
                        "dimension_unit": {
                          "type": "integer",
                          "default": 2
                        },
                        "quantity": {
                          "type": "integer",
                          "default": 1
                        },
                        "packaging_id": {
                          "type": "integer",
                          "nullable": true
                        },
                        "value": {
                          "type": "number"
                        },
                        "ref": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "notes": {
                          "type": "string"
                        },
                        "external_tracking_number": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "special_requirements": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Ignored when the service does not allow special requirements"
                  },
                  "surcharges": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "products": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Supplies as {productId: quantity}; honoured only when the service allows buying supplies"
                  },
                  "need_supplies_delivery": {
                    "type": "boolean"
                  },
                  "supplies_delivery_address_type": {
                    "type": "string",
                    "enum": [
                      "new",
                      "same_as_origin",
                      "same_as_destination"
                    ],
                    "default": "new"
                  },
                  "note": {
                    "type": "string"
                  },
                  "reference": {
                    "type": "string"
                  },
                  "coupon_code": {
                    "type": "string"
                  },
                  "selected_promotion_id": {
                    "type": "integer"
                  }
                }
              },
              "example": {
                "origin_type": "warehouse",
                "warehouse_id": 7,
                "delivery_name": "John Smith",
                "delivery_telephone": "6045550100",
                "delivery_address_1": "123 Main St",
                "delivery_postcode": "V6B1A1",
                "delivery_city": "Vancouver",
                "delivery_province": "BC",
                "delivery_country": "CA",
                "package": [
                  {
                    "weight": 3,
                    "length": 30,
                    "width": 20,
                    "height": 15,
                    "weight_unit": 2,
                    "dimension_unit": 2,
                    "quantity": 1
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Order updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "integer"
                        },
                        "total_price": {
                          "type": "number"
                        },
                        "price_breakdown": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "promotion_id": {
                          "type": "integer",
                          "nullable": true
                        },
                        "coupon_code": {
                          "type": "string",
                          "nullable": true
                        },
                        "promotion_discount": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 5501,
                    "status": 0,
                    "total_price": 23.0,
                    "price_breakdown": {
                      "sub_total": 20.35,
                      "tax_amount": 2.65,
                      "total": 23.0,
                      "currency": "CAD"
                    },
                    "promotion_id": null,
                    "coupon_code": null,
                    "promotion_discount": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Shipping order not found for this customer",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Shipping order not found."
                }
              }
            }
          },
          "422": {
            "description": "Validation failed, the service no longer exists, the packages do not fit the price plan's weight mode, or the service refuses a shipment it cannot price (code unpriced_refused)",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "message": "This shipment cannot be priced automatically.",
                  "code": "unpriced_refused"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error while updating",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Failed to update shipping order."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.id.put",
        "x-capability": "orders.shipping",
        "x-graphql": "customerShippingOrderUpdate"
      }
    },
    "/app/v1/shipping-orders/{id}/cancel": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerShippingOrderCancel",
        "summary": "Cancel a shipping order",
        "description": "Cancels a shipping order owned by the authenticated customer. Allowed only while the order is pending or confirmed. Payments on the order are voided and refunded to the customer's wallet balance, and the automatically created pickup order and any label order are removed. No request body. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "Order cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "integer"
                        },
                        "refund_amount": {
                          "type": "number",
                          "description": "Amount credited back to the wallet balance"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "id": 5501,
                    "status": 4,
                    "refund_amount": 23.0
                  },
                  "message": "Order cancelled. $23.00 refunded to your credit."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Shipping order not found for this customer",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Shipping order not found."
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error while cancelling",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Failed to cancel order."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.id.cancel.post",
        "x-capability": "orders.shipping",
        "x-graphql": "customerShippingOrderCancel"
      }
    },
    "/app/v1/shipping-orders/{id}/payment-info": {
      "get": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerShippingOrderPaymentInfo",
        "summary": "Get the payment information of a shipping order",
        "description": "Returns the amounts due on a shipping order owned by the authenticated customer and the customer's wallet balance. Shipping orders are paid in full only, so payment_options always holds the single option remaining_balance. Amounts are strings with two decimals. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment information",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "order_id": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "total_price": {
                          "type": "string"
                        },
                        "paid_amount": {
                          "type": "string"
                        },
                        "remaining_balance": {
                          "type": "string"
                        },
                        "user_balance": {
                          "type": "string"
                        },
                        "has_sufficient_balance": {
                          "type": "boolean"
                        },
                        "shortfall": {
                          "description": "0 when the balance is sufficient, otherwise the missing amount as a string"
                        },
                        "allow_online_payment": {
                          "type": "integer"
                        },
                        "payment_options": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "remaining_balance",
                                  "minimum_payment",
                                  "custom",
                                  "full_balance"
                                ]
                              },
                              "label": {
                                "type": "string"
                              },
                              "amount": {
                                "type": "number",
                                "nullable": true
                              },
                              "min_amount": {
                                "type": "number",
                                "description": "custom only"
                              },
                              "max_amount": {
                                "type": "number",
                                "description": "custom only"
                              },
                              "description": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "order_id": 5501,
                    "currency": "CAD",
                    "total_price": "23.00",
                    "paid_amount": "0.00",
                    "remaining_balance": "23.00",
                    "user_balance": "50.00",
                    "has_sufficient_balance": true,
                    "shortfall": 0,
                    "allow_online_payment": 1,
                    "payment_options": [
                      {
                        "type": "remaining_balance",
                        "label": "Pay Remaining Balance",
                        "amount": 23.0,
                        "description": "Pay the remaining balance to complete payment"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "The order is already fully paid",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "This order has already been fully paid."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "500": {
            "description": "Order not found in the customer's business, or an unexpected error",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Failed to load payment info."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.id.payment-info.get",
        "x-capability": "orders.shipping",
        "x-graphql": "customerShippingOrderPaymentInfo"
      }
    },
    "/app/v1/shipping-orders/{id}/pay": {
      "post": {
        "tags": [
          "Customer"
        ],
        "operationId": "customerShippingOrderPay",
        "summary": "Pay a shipping order from the wallet balance",
        "description": "Pays the full remaining balance of a shipping order owned by the authenticated customer from the customer's wallet balance. Partial payment is not supported; payment_type may be sent but is not used. A pending order that becomes fully paid is confirmed. Needs orders.shipping on the token; answered exactly as the internal customer route.",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Order id"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_type": {
                    "type": "string",
                    "example": "remaining_balance",
                    "description": "Not used; the full remaining balance is always charged"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "order_id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "integer"
                        },
                        "amount_paid": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Payment of $23.00 processed successfully.",
                  "data": {
                    "order_id": 5501,
                    "status": 1,
                    "amount_paid": "23.00"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The order is already fully paid",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "This order has already been fully paid."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "422": {
            "description": "Insufficient wallet balance",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Insufficient balance."
                }
              }
            }
          },
          "500": {
            "description": "Order not found in the customer's business, or the payment failed",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Payment failed: ..."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.customer.shipping-orders.id.pay.post",
        "x-capability": "orders.shipping",
        "x-graphql": "customerShippingOrderPay"
      }
    },
    "/app/v1/deals": {
      "get": {
        "summary": "GET /app/v1/deals",
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.customer.deals.get",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-capability": "deals",
        "description": "Needs deals on the token; answered exactly as the internal customer route.",
        "operationId": "customerDealsGet"
      }
    },
    "/app/v1/uniorder/rate": {
      "post": {
        "tags": [
          "Orders"
        ],
        "summary": "Uniorder: rate a shipment (self delivery and label carrier services)",
        "description": "A price quote on a complete address at both ends, answered as one list of rates to choose from. A customer (or sub-account) caller is quoted only the services open to it: self delivery needs its place-order permission, the client's delivery service and the requested type's own switch (D, P or P2P); a label service needs its place-order permission and the client's label service; signed in through a platform app, that app's orders.delivery or orders.label capability must also be on. Access: these single-order uniorder endpoints (rate, create, show, label, label purchase, tracking, cancel) require the account's API permission, except for a customer signed in through a platform app session whose app has orders.delivery or orders.label on; that session needs no API permission. The batch endpoints always require it. A service it may not order is left out of rates and errors (labels are then not asked of the carriers); when neither is open the answer is HTTP 403 with result false and code SERVICE_NOT_AVAILABLE. Clients, employees and integrations are unaffected. The sender's and the recipient's street line, city, province, country and postcode are all required; only from_address_2 and to_address_2 are optional. For type P (pickup) the sender is the pickup stop and the recipient is where the parcel goes. Nothing is created or booked. v1 and v2 are unchanged.\n\nEvery rate has a `type` and a `rate_id`:\n- `self_delivery`: delivery by the business, priced on the caller's (or the named customer's) plan. At most one per quote. How the business carries it is not part of the answer.\n- `label_service`: one per service of each label carrier account, only when quote_labels is true.\n\n`rate_id` is an opaque token naming the choice (self_delivery: channel and customer; label_service: account, carrier and service) and the quoted price. It is valid for 30 minutes and only for the caller it was issued to; order at a rate by passing it to POST /v1/uniorder. Whatever could not be quoted is listed in `errors` with its type; an address outside the delivery area is an error of type self_delivery with code OUT_OF_DELIVERY_AREA. `result` is true when at least one rate was found.\n\nA client or employee may quote for one of its customers (customer_id or customer_code) so the price follows that customer's plan; a delivery window (time_window_start / time_window_end) is taken into account; channel_id must be one of the business's own channels. Taxes are worked out from the provinces given. Needs orders.delivery or orders.label on the token; answered exactly as the internal customer route.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderRateV3"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "description": "True when at least one rate was found."
                    },
                    "rates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "rate_id",
                          "type",
                          "shipping_price",
                          "currency",
                          "price_details"
                        ],
                        "properties": {
                          "rate_id": {
                            "type": "string",
                            "description": "Opaque token to order at this rate. Valid for 30 minutes, for the caller it was issued to only."
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "self_delivery",
                              "label_service"
                            ]
                          },
                          "shipping_price": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Total, taxes included for self_delivery. Null for a self_delivery rate that is inside the delivery area but has no price yet (see warning); the order is priced once created."
                          },
                          "currency": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "price_details": {
                            "type": [
                              "object",
                              "array",
                              "null"
                            ],
                            "description": "self_delivery: {shipping_fee, sub_total (pre-tax), tax_details, tax_zone_id, ...}. label_service: the carrier service's price lines."
                          },
                          "channel_id": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "self_delivery only: the channel the rate was priced on."
                          },
                          "warning": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "self_delivery only."
                          },
                          "shipping_method_id": {
                            "type": "integer",
                            "description": "label_service only: the label account."
                          },
                          "shipping_method_name": {
                            "type": "string",
                            "description": "label_service only."
                          },
                          "carrier_name": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "label_service: the carrier. self_delivery: the brand the order would print under (the brand rules of its shipping label), else the business's own name."
                          },
                          "carrier_id": {
                            "type": "string",
                            "description": "label_service only."
                          },
                          "service_code": {
                            "type": "string",
                            "description": "label_service only."
                          },
                          "service_name": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "label_service: the carrier's service. self_delivery: the display name of the channel the rate was priced on; null without a channel."
                          },
                          "transit_days": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "label_service only, when the carrier gives it."
                          }
                        }
                      }
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "self_delivery",
                              "label_service"
                            ]
                          },
                          "code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "OUT_OF_DELIVERY_AREA when the address is outside the delivery area."
                          },
                          "message": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "selfDelivery": {
                    "summary": "Self delivery only",
                    "value": {
                      "result": true,
                      "rates": [
                        {
                          "rate_id": "eyJpdiI6Ik1rT2Z...",
                          "type": "self_delivery",
                          "channel_id": null,
                          "carrier_name": "Swift Courier",
                          "service_name": null,
                          "shipping_price": "14.60",
                          "currency": "CAD",
                          "price_details": {
                            "shipping_fee": 12.92,
                            "sub_total": "12.92",
                            "tax_details": [
                              {
                                "tax_number_id": 2,
                                "tax_name": "HST",
                                "tax_rate": "13.00",
                                "tax": "1.68"
                              }
                            ],
                            "tax_zone_id": 3
                          },
                          "warning": null
                        }
                      ],
                      "errors": []
                    }
                  },
                  "withLabelRates": {
                    "summary": "quote_labels: self delivery plus every label account's services",
                    "value": {
                      "result": true,
                      "rates": [
                        {
                          "rate_id": "eyJpdiI6Ik1rT2Z...",
                          "type": "self_delivery",
                          "channel_id": null,
                          "carrier_name": "Swift Courier",
                          "service_name": null,
                          "shipping_price": "14.60",
                          "currency": "CAD",
                          "price_details": {
                            "shipping_fee": 12.92,
                            "sub_total": "12.92",
                            "tax_details": [
                              {
                                "tax_number_id": 2,
                                "tax_name": "HST",
                                "tax_rate": "13.00",
                                "tax": "1.68"
                              }
                            ],
                            "tax_zone_id": 3
                          },
                          "warning": null
                        },
                        {
                          "rate_id": "eyJpdiI6IlpxR0...",
                          "type": "label_service",
                          "shipping_price": "15.18",
                          "currency": "CAD",
                          "price_details": [],
                          "shipping_method_id": 71,
                          "shipping_method_name": "Canada Post",
                          "carrier_name": "canadapost",
                          "carrier_id": "CPTEST",
                          "service_code": "canadapost_expedited_parcel",
                          "service_name": "CANADAPOST EXPEDITED PARCEL",
                          "transit_days": 2
                        },
                        {
                          "rate_id": "eyJpdiI6IlpxR0...",
                          "type": "label_service",
                          "shipping_price": "18.40",
                          "currency": "CAD",
                          "price_details": [],
                          "shipping_method_id": 72,
                          "shipping_method_name": "UPS",
                          "carrier_name": "ups",
                          "carrier_id": "UPS1",
                          "service_code": "ups_standard",
                          "service_name": "UPS STANDARD",
                          "transit_days": 3
                        }
                      ],
                      "errors": []
                    }
                  },
                  "outOfDeliveryArea": {
                    "summary": "Outside the delivery area, no label quote asked",
                    "value": {
                      "result": false,
                      "rates": [],
                      "errors": [
                        {
                          "type": "self_delivery",
                          "code": "OUT_OF_DELIVERY_AREA",
                          "message": "The delivery address is outside the delivery area."
                        }
                      ]
                    }
                  },
                  "unpriced": {
                    "summary": "Inside the delivery area, no price yet",
                    "value": {
                      "result": true,
                      "rates": [
                        {
                          "rate_id": "eyJpdiI6Ik1rT2Z...",
                          "type": "self_delivery",
                          "channel_id": null,
                          "carrier_name": "Swift Courier",
                          "service_name": null,
                          "shipping_price": null,
                          "currency": null,
                          "price_details": null,
                          "warning": null
                        }
                      ],
                      "errors": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "operationId": "uniorderRate",
        "x-route-name": "openapp.customer.uniorder.rate.post",
        "x-graphql": "uniorderRate",
        "x-capability": "orders.delivery|orders.label"
      }
    },
    "/app/v1/uniorder": {
      "post": {
        "tags": [
          "Orders"
        ],
        "summary": "Uniorder: create an order at a rate",
        "operationId": "uniorderCreate",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Creates an order at a rate returned by POST /v1/uniorder/rate. The rate_id alone decides the service; the same rules as POST /v1/uniorder/rate decide, again at create time, whether a customer (or sub-account) caller may order that service; when it may not, the answer is HTTP 403 with result false and code SERVICE_NOT_AVAILABLE and nothing is created. Otherwise the body carries the shipment in the quote's shape (from_*, to_*, packages) and the order's own details.\n\n- `self_delivery`: a delivery order on the quote's customer and channel, created as POST /v1/client/orderCreate would create it (needs the place-order permission). For type D the recipient is the order's stop. The sender is kept as its pickup address only with need_pick_up 1; without it, from_* prices the quote only and the order starts from the account's default shipping-from address, which GET /v1/uniorder/{orderId} returns as from. For type P the sender is the stop.\n- `label_service`: a label order on the quote's account, then the label is bought at the carrier service the quote named. The service is priced again for the order, so shipping_price may differ from quoted_price. When the label cannot be bought, the order is kept and the answer is HTTP 200 with result false, code LABEL_PURCHASE_FAILED and the order id; do not submit it again — buy the label with POST /v1/uniorder/{orderId}/label.\n\nA rate_id that is malformed, expired (30 minutes) or was issued to another caller is refused with RATE_ID_INVALID and nothing is created. Send an Idempotency-Key header to make retries safe. Needs orders.delivery or orders.label on the token; answered exactly as the internal customer route.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. A retry with the same key and body answers with the first result instead of creating a second order."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderCreateV3"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created (or label not purchased: see code)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "description": "true: the order was created (and, for label_service, the label bought). false: see code."
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "self_delivery",
                        "label_service"
                      ]
                    },
                    "id": {
                      "type": "integer",
                      "description": "Order id. Present on success, and on LABEL_PURCHASE_FAILED (the order was kept)."
                    },
                    "ref": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "tracking_numbers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "packages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "ref": {
                            "type": "string"
                          },
                          "tracking_number": {
                            "type": "string"
                          },
                          "external_tracking_number": {
                            "type": "string"
                          }
                        }
                      },
                      "description": "self_delivery only."
                    },
                    "shipping_price": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The price charged for the order. It is priced when the order is created and may differ from quoted_price."
                    },
                    "currency": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "price_details": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "self_delivery only: shipping_fee, sub_total (pre-tax), tax_details, tax_zone_id, ..."
                    },
                    "quoted_price": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The price the rate_id was quoted at."
                    },
                    "warning": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "self_delivery only."
                    },
                    "label": {
                      "type": "object",
                      "description": "label_service only.",
                      "properties": {
                        "shipping_method_id": {
                          "type": "integer"
                        },
                        "carrier_name": {
                          "type": "string"
                        },
                        "carrier_id": {
                          "type": "string"
                        },
                        "service_code": {
                          "type": "string"
                        },
                        "service_name": {
                          "type": "string"
                        },
                        "main_tracking_number": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "carrier_tracking_numbers": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "label_status": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "ready: shipping_label carries the PDF. pending / failed: purchased, the file is not in yet."
                        },
                        "shipping_label": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Base64 PDF, when ready."
                        }
                      }
                    },
                    "code": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "LABEL_PURCHASE_FAILED: the label order was created and kept (id), but the label was not bought. Do not submit it again; buy the label with POST /v1/uniorder/{orderId}/label."
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "examples": {
                  "selfDelivery": {
                    "summary": "Self delivery created",
                    "value": {
                      "result": true,
                      "type": "self_delivery",
                      "id": 123456,
                      "ref": "ORDER-1001",
                      "tracking_numbers": [
                        "SR26092800001"
                      ],
                      "packages": [
                        {
                          "id": 987,
                          "ref": "PKG-1",
                          "tracking_number": "SR26092800001",
                          "external_tracking_number": ""
                        }
                      ],
                      "shipping_price": "14.60",
                      "currency": "CAD",
                      "price_details": {
                        "shipping_fee": 12.92,
                        "sub_total": "12.92",
                        "tax_details": [
                          {
                            "tax_number_id": 2,
                            "tax_name": "HST",
                            "tax_rate": "13.00",
                            "tax": "1.68"
                          }
                        ],
                        "tax_zone_id": 3
                      },
                      "quoted_price": "14.60",
                      "warning": null
                    }
                  },
                  "labelService": {
                    "summary": "Label order created and label bought",
                    "value": {
                      "result": true,
                      "type": "label_service",
                      "id": 123457,
                      "ref": "ORDER-1002",
                      "tracking_numbers": [
                        "SR26092800002"
                      ],
                      "shipping_price": "18.40",
                      "currency": "CAD",
                      "quoted_price": "18.40",
                      "label": {
                        "shipping_method_id": 72,
                        "carrier_name": "ups",
                        "carrier_id": "UPS1",
                        "service_code": "ups_standard",
                        "service_name": "UPS STANDARD",
                        "main_tracking_number": "1Z999AA10123456784",
                        "carrier_tracking_numbers": [
                          "1Z999AA10123456784"
                        ],
                        "label_status": "ready",
                        "shipping_label": "JVBERi0xLjQK..."
                      }
                    }
                  },
                  "labelPurchaseFailed": {
                    "summary": "Label order kept, label not bought",
                    "value": {
                      "result": false,
                      "code": "LABEL_PURCHASE_FAILED",
                      "type": "label_service",
                      "id": 123458,
                      "ref": "ORDER-1003",
                      "tracking_numbers": [
                        "SR26092800003"
                      ],
                      "quoted_price": "18.40",
                      "message": "The quoted service is not offered for this shipment."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Nothing created: invalid rate_id, validation failure, or the order refused",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "code": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "RATE_ID_INVALID, VALIDATION_FAILED, OUT_OF_DELIVERY_AREA, or the v1 create's own code."
                    },
                    "message": {}
                  }
                },
                "examples": {
                  "rateIdInvalid": {
                    "summary": "rate_id invalid or expired",
                    "value": {
                      "result": false,
                      "code": "RATE_ID_INVALID",
                      "message": "rate_id is invalid or expired. Request a new quote."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "409": {
            "description": "Idempotency-Key conflict or still in progress"
          }
        },
        "x-route-name": "openapp.customer.uniorder.post",
        "x-graphql": "uniorderCreate",
        "x-capability": "orders.delivery|orders.label"
      }
    },
    "/app/v1/uniorder/{orderId}/label": {
      "post": {
        "tags": [
          "Orders"
        ],
        "summary": "Uniorder: buy the label of a label order kept without one",
        "operationId": "uniorderPurchaseLabel",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Buys the label of a label order created by POST /v1/uniorder whose label was not bought (LABEL_PURCHASE_FAILED). For a customer (or sub-account) caller the label service must still be open, by the same rules as POST /v1/uniorder; otherwise HTTP 403, code SERVICE_NOT_AVAILABLE. The service is the one chosen when the order was created; the order is priced again for it, so shipping_price may differ from quoted_price. Pass rate_id (a label_service rate from POST /v1/uniorder/rate for the same account) to buy at that service instead. A label already bought is returned as it is and is not bought again. The answer has the same shape as POST /v1/uniorder for a label_service rate; a purchase that fails again answers HTTP 200 with result false and code LABEL_PURCHASE_FAILED. Needs orders.delivery or orders.label on the token; answered exactly as the internal customer route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The order id POST /v1/uniorder returned."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. A retry with the same key and body answers with the first result."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rate_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Optional. A label_service rate_id of the same account, to buy at its service instead of the one chosen when the order was created."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Label bought (or already bought), or still not bought: see code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "description": "true: the order was created (and, for label_service, the label bought). false: see code."
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "self_delivery",
                        "label_service"
                      ]
                    },
                    "id": {
                      "type": "integer",
                      "description": "Order id. Present on success, and on LABEL_PURCHASE_FAILED (the order was kept)."
                    },
                    "ref": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "tracking_numbers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "packages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "ref": {
                            "type": "string"
                          },
                          "tracking_number": {
                            "type": "string"
                          },
                          "external_tracking_number": {
                            "type": "string"
                          }
                        }
                      },
                      "description": "self_delivery only."
                    },
                    "shipping_price": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The price charged for the order. It is priced when the order is created and may differ from quoted_price."
                    },
                    "currency": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "price_details": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "self_delivery only: shipping_fee, sub_total (pre-tax), tax_details, tax_zone_id, ..."
                    },
                    "quoted_price": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The price the rate_id was quoted at."
                    },
                    "warning": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "self_delivery only."
                    },
                    "label": {
                      "type": "object",
                      "description": "label_service only.",
                      "properties": {
                        "shipping_method_id": {
                          "type": "integer"
                        },
                        "carrier_name": {
                          "type": "string"
                        },
                        "carrier_id": {
                          "type": "string"
                        },
                        "service_code": {
                          "type": "string"
                        },
                        "service_name": {
                          "type": "string"
                        },
                        "main_tracking_number": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "carrier_tracking_numbers": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "label_status": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "ready: shipping_label carries the PDF. pending / failed: purchased, the file is not in yet."
                        },
                        "shipping_label": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Base64 PDF, when ready."
                        }
                      }
                    },
                    "code": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "LABEL_PURCHASE_FAILED: the label order was created and kept (id), but the label was not bought. Do not submit it again; buy the label with POST /v1/uniorder/{orderId}/label."
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "examples": {
                  "bought": {
                    "summary": "Label bought",
                    "value": {
                      "result": true,
                      "type": "label_service",
                      "id": 123457,
                      "ref": "ORDER-1002",
                      "tracking_numbers": [
                        "SR26092800002"
                      ],
                      "shipping_price": "18.40",
                      "currency": "CAD",
                      "quoted_price": "18.40",
                      "label": {
                        "shipping_method_id": 72,
                        "carrier_name": "ups",
                        "carrier_id": "UPS1",
                        "service_code": "ups_standard",
                        "service_name": "UPS STANDARD",
                        "main_tracking_number": "1Z999AA10123456784",
                        "carrier_tracking_numbers": [
                          "1Z999AA10123456784"
                        ],
                        "label_status": "ready",
                        "shipping_label": "JVBERi0xLjQK..."
                      }
                    }
                  },
                  "stillNotBought": {
                    "summary": "The carrier refused again",
                    "value": {
                      "result": false,
                      "code": "LABEL_PURCHASE_FAILED",
                      "type": "label_service",
                      "id": 123458,
                      "ref": "ORDER-1003",
                      "tracking_numbers": [
                        "SR26092800003"
                      ],
                      "quoted_price": "18.40",
                      "message": "Insufficient balance"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid rate_id, or no service chosen for this order and no rate_id given",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "code": {
                      "type": "string"
                    },
                    "message": {}
                  }
                },
                "examples": {
                  "rateIdInvalid": {
                    "summary": "rate_id invalid, expired, or of another account",
                    "value": {
                      "result": false,
                      "code": "RATE_ID_INVALID",
                      "message": "rate_id is invalid or expired, or is not a label_service rate of this order's account. Request a new quote."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope"
          },
          "404": {
            "description": "Not a label order of the caller",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency-Key conflict or still in progress"
          }
        },
        "x-route-name": "openapp.customer.uniorder.orderId.label.post",
        "x-graphql": "uniorderPurchaseLabel",
        "x-capability": "orders.delivery|orders.label"
      },
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Uniorder: download the label",
        "operationId": "uniorderLabel",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "The label PDF of the order, base64 in `pdf_data`. A self delivery gives the business's own label (`hide_sender_address` / `hide_receiver_address` = 1 leave an address off). A label order gives the carrier label it bought; a label is never bought here. A label not bought yet answers 409 LABEL_PURCHASE_FAILED — buy it with POST /v1/uniorder/{orderId}/label. A label bought whose file the carrier has not produced yet answers 200 with result false and `label_status` pending (or failed). Needs orders.delivery or orders.label on the token; answered exactly as the internal customer route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The order id POST /v1/uniorder returned."
          },
          {
            "name": "hide_sender_address",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "description": "self_delivery only."
          },
          {
            "name": "hide_receiver_address",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "description": "self_delivery only."
          }
        ],
        "responses": {
          "200": {
            "description": "The PDF, or a label file not produced yet",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "self_delivery",
                        "label_service"
                      ]
                    },
                    "id": {
                      "type": "integer"
                    },
                    "format": {
                      "type": "string",
                      "enum": [
                        "pdf"
                      ]
                    },
                    "label_code": {
                      "type": "string",
                      "description": "self_delivery: the sorting code printed on the label."
                    },
                    "label_status": {
                      "type": "string",
                      "description": "label_service: ready, pending or failed."
                    },
                    "tracking_numbers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "pdf_data": {
                      "type": "string",
                      "description": "Base64 PDF."
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": true,
                  "type": "self_delivery",
                  "id": 123456,
                  "format": "pdf",
                  "label_code": "MTL-01",
                  "tracking_numbers": [
                    "SR26092800001"
                  ],
                  "pdf_data": "JVBERi0xLjQK..."
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Not a self delivery or label order of the caller",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found"
                }
              }
            }
          },
          "409": {
            "description": "Label order whose label has not been bought",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "code": "LABEL_PURCHASE_FAILED",
                  "type": "label_service",
                  "id": 123458,
                  "message": "The label has not been bought. Buy it with POST /v1/uniorder/123458/label."
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          }
        },
        "x-route-name": "openapp.customer.uniorder.orderId.label.get",
        "x-graphql": "uniorderLabel",
        "x-capability": "orders.delivery|orders.label"
      }
    },
    "/app/v1/uniorder/{orderId}/cancel": {
      "post": {
        "tags": [
          "Orders"
        ],
        "summary": "Uniorder: cancel an order",
        "operationId": "uniorderCancel",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Cancels an order created by POST /v1/uniorder: a self delivery or a label order of the caller. A label is voided with its carrier first; a label the carrier does not void leaves the order unchanged (LABEL_CANCEL_FAILED). A delivery is withdrawn wherever it is being carried first; when that is refused the order is unchanged (ORDER_CANCEL_REFUSED). An order already cancelled answers success with already_cancelled true, so a retry is safe. Orders of other families (storage, shipping, moving, ...) are not found here. A refusal fires order.cancel_failed when the account has subscribed to it. Needs orders.delivery or orders.label on the token; answered exactly as the internal customer route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The order id POST /v1/uniorder returned."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. A retry with the same key answers with the first result."
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled, or already cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "self_delivery",
                        "label_service"
                      ]
                    },
                    "id": {
                      "type": "integer"
                    },
                    "already_cancelled": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "cancelled": {
                    "summary": "Cancelled",
                    "value": {
                      "result": true,
                      "type": "self_delivery",
                      "id": 123456,
                      "already_cancelled": false,
                      "message": "The order has been cancelled."
                    }
                  },
                  "already": {
                    "summary": "Already cancelled",
                    "value": {
                      "result": true,
                      "type": "label_service",
                      "id": 123457,
                      "already_cancelled": true,
                      "message": "The order was already cancelled."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Not a self delivery or label order of the caller",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found"
                }
              }
            }
          },
          "409": {
            "description": "Not cancelled; the order is unchanged",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "ORDER_STATUS_NOT_CANCELLABLE",
                        "ORDER_CANCEL_REFUSED",
                        "LABEL_CANCEL_FAILED",
                        "IDEMPOTENCY_CONFLICT",
                        "IDEMPOTENCY_IN_PROGRESS"
                      ]
                    },
                    "type": {
                      "type": "string"
                    },
                    "id": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "notCancellable": {
                    "summary": "Too late to cancel",
                    "value": {
                      "result": false,
                      "code": "ORDER_STATUS_NOT_CANCELLABLE",
                      "type": "self_delivery",
                      "id": 123456,
                      "message": "The order can no longer be cancelled."
                    }
                  },
                  "refused": {
                    "summary": "Refused",
                    "value": {
                      "result": false,
                      "code": "ORDER_CANCEL_REFUSED",
                      "type": "self_delivery",
                      "id": 123456,
                      "message": "The order cannot be cancelled now. The order is unchanged."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          }
        },
        "x-route-name": "openapp.customer.uniorder.orderId.cancel.post",
        "x-graphql": "uniorderCancel",
        "x-capability": "orders.delivery|orders.label"
      }
    },
    "/app/v1/uniorder/{orderId}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Uniorder: read an order",
        "operationId": "uniorder",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "One self delivery or label order of the caller. `status` is one of: pending, in_transit, out_for_pickup, out_for_delivery, ready_for_self_pickup, delivered, exception, cancelled (self delivery); label_pending, label_purchased, cancelled (label order — where the parcel is, GET /v1/uniorder/{orderId}/tracking says). A self delivery reads the same however it is carried. A label order carries a `label` block: account, carrier, service, the carrier's tracking numbers and `label_status` (not_purchased, pending, ready, failed). Needs orders.delivery or orders.label on the token; answered exactly as the internal customer route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The order id POST /v1/uniorder returned."
          }
        ],
        "responses": {
          "200": {
            "description": "The order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "self_delivery",
                        "label_service"
                      ]
                    },
                    "id": {
                      "type": "integer"
                    },
                    "ref": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "order_type": {
                      "type": "string",
                      "description": "D, P, P2P, I (self delivery) or L (label)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "in_transit",
                        "out_for_pickup",
                        "out_for_delivery",
                        "ready_for_self_pickup",
                        "delivered",
                        "exception",
                        "cancelled",
                        "label_pending",
                        "label_purchased"
                      ]
                    },
                    "status_group": {
                      "type": "string",
                      "enum": [
                        "pending_payment",
                        "active",
                        "completed",
                        "exception",
                        "cancelled"
                      ],
                      "description": "Additive. The status read the same way as the platform app order list: the group an app colours by."
                    },
                    "status_label": {
                      "type": "string",
                      "description": "Additive. The status name in the request language (Accept-Language)."
                    },
                    "created_at": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "scheduled_date": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "time_window_start": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "time_window_end": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "from": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "company_name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "telephone": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "address": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "address_2": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "city": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "province": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "postcode": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    },
                    "to": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "company_name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "telephone": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "address": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "address_2": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "city": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "province": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "postcode": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    },
                    "packages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "ref": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tracking_number": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "external_tracking_number": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "weight": {},
                          "weight_unit": {},
                          "length": {},
                          "width": {},
                          "height": {},
                          "dimension_unit": {}
                        }
                      }
                    },
                    "shipping_price": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "currency": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "price_details": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "self_delivery only."
                    },
                    "label": {
                      "type": "object",
                      "description": "label_service only.",
                      "properties": {
                        "shipping_method_id": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "carrier_name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "carrier_id": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "service_code": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "carrier_tracking_numbers": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "label_status": {
                          "type": "string",
                          "enum": [
                            "not_purchased",
                            "pending",
                            "ready",
                            "failed"
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "type": "self_delivery",
                  "id": 123456,
                  "ref": "ORDER-1001",
                  "order_type": "D",
                  "status": "in_transit",
                  "created_at": "2026-09-28 10:00:00",
                  "scheduled_date": "2026-09-29",
                  "time_window_start": null,
                  "time_window_end": null,
                  "from": {
                    "name": "Sender Co",
                    "company_name": null,
                    "telephone": "5145550100",
                    "email": null,
                    "address": "1010 Rue Sainte-Catherine O",
                    "address_2": "Suite 400",
                    "city": "Montreal",
                    "province": "QC",
                    "country": "CA",
                    "postcode": "H3B1G1"
                  },
                  "to": {
                    "name": "Jane Recipient",
                    "company_name": null,
                    "telephone": "5145550199",
                    "email": "jane@example.com",
                    "address": "6841 Rue Saint-Denis",
                    "address_2": "Apt 2",
                    "city": "Montreal",
                    "province": "QC",
                    "country": "CA",
                    "postcode": "H2S2S3"
                  },
                  "packages": [
                    {
                      "id": 987,
                      "ref": "PKG-1",
                      "tracking_number": "SR26092800001",
                      "external_tracking_number": "",
                      "weight": "2.5",
                      "weight_unit": 2,
                      "length": "30",
                      "width": "20",
                      "height": "15",
                      "dimension_unit": 2
                    }
                  ],
                  "shipping_price": "14.60",
                  "currency": "CAD",
                  "price_details": {
                    "shipping_fee": 12.92,
                    "sub_total": "12.92",
                    "tax_details": [
                      {
                        "tax_name": "QST",
                        "tax_rate": "9.975",
                        "tax": "1.29"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Not a self delivery or label order of the caller",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          }
        },
        "x-route-name": "openapp.customer.uniorder.orderId.get",
        "x-graphql": "uniorder",
        "x-capability": "orders.delivery|orders.label"
      }
    },
    "/app/v1/uniorder/{orderId}/tracking": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Uniorder: track an order",
        "operationId": "uniorderTracking",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "The order's timeline, newest first: each event's `code` (OTEP status), `description`, `location` and time; proofs of delivery with a signed URL. A self delivery's timeline reads the same however it is carried and every event has `source` shipper. A label order adds a `carrier` block (name, tracking number, tracking URL, status) and its carrier events have `source` carrier. Needs orders.delivery or orders.label on the token; answered exactly as the internal customer route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The order id POST /v1/uniorder returned."
          }
        ],
        "responses": {
          "200": {
            "description": "The timeline",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "type": {
                      "type": "string"
                    },
                    "id": {
                      "type": "integer"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "in_transit",
                        "out_for_pickup",
                        "out_for_delivery",
                        "ready_for_self_pickup",
                        "delivered",
                        "exception",
                        "cancelled",
                        "label_pending",
                        "label_purchased"
                      ]
                    },
                    "tracking_numbers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "location": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "time": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Local time, Y-m-d H:i:s."
                          },
                          "time_zone": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gmt_offset": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "timestamp": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "shipper",
                              "carrier"
                            ]
                          }
                        }
                      }
                    },
                    "proofs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "url": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "uploaded_at": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    },
                    "carrier": {
                      "type": "object",
                      "description": "label_service only.",
                      "properties": {
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "tracking_number": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "tracking_url": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "type": "self_delivery",
                  "id": 123456,
                  "status": "in_transit",
                  "tracking_numbers": [
                    "SR26092800001"
                  ],
                  "events": [
                    {
                      "code": "IN_TRANSIT",
                      "description": "Your shipment is in transit.",
                      "location": "Montreal,QC",
                      "time": "2026-09-29 09:12:00",
                      "time_zone": "America/Toronto",
                      "gmt_offset": "-04:00",
                      "timestamp": 1790687520,
                      "source": "shipper"
                    }
                  ],
                  "proofs": []
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Not a self delivery or label order of the caller",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "code": "ORDER_NOT_FOUND",
                  "message": "Order not found"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope"
          }
        },
        "x-route-name": "openapp.customer.uniorder.orderId.tracking.get",
        "x-graphql": "uniorderTracking",
        "x-capability": "orders.delivery|orders.label"
      }
    },
    "/app/v1/driver/routes": {
      "get": {
        "tags": [
          "Driver"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "isProcessing",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "required": false
          },
          {
            "in": "query",
            "name": "isHistory",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "required": false
          },
          {
            "in": "query",
            "name": "isHistory",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "required": false
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer"
            },
            "required": false
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "type": "integer"
            },
            "required": false
          },
          {
            "in": "query",
            "name": "sort",
            "schema": {
              "type": "string"
            },
            "required": false
          },
          {
            "in": "query",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "Filter by route ID.",
            "required": false
          }
        ],
        "summary": "Get routes for one driver",
        "description": "Each route's total and per-status count are this driver's orders on that route, not every order on the route. Recurring pickups (additive, after every existing key): recurring_pickup_route tells a route generated from a recurring pickup template; allow_adhoc_pickups and allow_deliveries are its two switches (true for every other route, and before the recurring pickup migrations). Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route.",
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "route_type": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "date": {
                            "type": "string"
                          },
                          "operation_mode": {
                            "type": "integer"
                          },
                          "allow_rescheduled_by_same_driver": {
                            "type": "integer"
                          },
                          "allow_hands_off_order_by_driver": {
                            "type": "integer"
                          },
                          "allow_reset_order_status_by_driver": {
                            "type": "integer"
                          },
                          "allow_add_order_by_driver": {
                            "type": "integer"
                          },
                          "allow_add_manual_order_by_driver": {
                            "type": "integer"
                          },
                          "driver_alias": {
                            "type": "string"
                          },
                          "vehicle_type": {
                            "type": "string"
                          },
                          "distance": {
                            "type": "integer"
                          },
                          "geometry": {
                            "type": "string",
                            "nullable": true,
                            "description": "Encoded route geometry; null if the route has no stored geometry."
                          },
                          "total": {
                            "type": "integer",
                            "description": "Number of orders assigned to this driver on the route, not every order on the route."
                          },
                          "count": {
                            "type": "object",
                            "description": "Per-status counts of this driver's orders on the route.",
                            "properties": {
                              "already_planned": {
                                "type": "integer"
                              }
                            }
                          },
                          "recurring_pickup_route": {
                            "type": "boolean",
                            "description": "Generated from a recurring pickup template"
                          },
                          "allow_adhoc_pickups": {
                            "type": "boolean",
                            "description": "Non-recurring pickup orders may join the route (true for every non-recurring route)"
                          },
                          "allow_deliveries": {
                            "type": "boolean",
                            "description": "Delivery orders may join the route (true for every non-recurring route)"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 323,
                      "route_type": 2,
                      "name": "20210220171743",
                      "date": "2021-02-20",
                      "operation_mode": 0,
                      "allow_rescheduled_by_same_driver": 1,
                      "allow_hands_off_order_by_driver": 0,
                      "allow_reset_order_status_by_driver": 0,
                      "allow_add_order_by_driver": 0,
                      "allow_add_manual_order_by_driver": 0,
                      "driver_alias": "XXX",
                      "vehicle_type": "1 (1: Car, 2: Truck, 3: Motorcycle, 4: Bicycle 5:Pedestrian)",
                      "distance": 2321231,
                      "geometry": "XXX",
                      "total": 1,
                      "count": {
                        "already_planned": 1
                      },
                      "recurring_pickup_route": false,
                      "allow_adhoc_pickups": true,
                      "allow_deliveries": true
                    },
                    {
                      "id": 12,
                      "name": "20200511",
                      "date": "2020-05-11",
                      "operation_mode": 0,
                      "allow_rescheduled_by_same_driver": 1,
                      "allow_hands_off_order_by_driver": 0,
                      "allow_reset_order_status_by_driver": 0,
                      "allow_add_order_by_driver": 0,
                      "allow_add_manual_order_by_driver": 0,
                      "driver_alias": "XXX",
                      "distance": 43242321,
                      "geometry": "XXX",
                      "total": 11,
                      "count": {
                        "already_planned": 11
                      },
                      "recurring_pickup_route": false,
                      "allow_adhoc_pickups": true,
                      "allow_deliveries": true
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.routes.get",
        "x-capability": "driver.routes",
        "x-graphql": "driverRoutes",
        "operationId": "driverRoutes"
      }
    },
    "/app/v1/driver/boards": {
      "get": {
        "tags": [
          "Driver Route Board"
        ],
        "summary": "List the Route Boards visible to the driver",
        "description": "Boards of the driver's own pool (own fleet, or their contractor's) that are scheduled, open, filled or closed, dated today or later, and whose eligibility the driver passes. Each row carries the seat counts and the driver's own claims on it. A seat-mode (\"Grab a Seat\") board additionally carries capacity / quota_taken / my_pooled / settled. Driver apps only; needs driver.board on the token. Answered exactly as the internal driver route.",
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "mode": {
                            "type": "string",
                            "enum": [
                              "route",
                              "seat",
                              "bid"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "scheduled",
                              "open",
                              "filled",
                              "closed"
                            ]
                          },
                          "opens_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "closes_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "is_open": {
                            "type": "boolean"
                          },
                          "seats": {
                            "type": "integer"
                          },
                          "open_seats": {
                            "type": "integer"
                          },
                          "standby_limit": {
                            "type": "integer"
                          },
                          "withdraw_policy": {
                            "type": "string",
                            "enum": [
                              "allowed",
                              "denied",
                              "until_cutoff"
                            ]
                          },
                          "withdraw_cutoff_hours": {
                            "type": "integer",
                            "nullable": true
                          },
                          "my_primary": {
                            "type": "integer"
                          },
                          "my_standby": {
                            "type": "integer"
                          },
                          "my_pooled": {
                            "type": "integer",
                            "description": "Seat-mode boards: 1 when the caller holds a pooled seat on this board"
                          },
                          "capacity": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Seat-mode boards: number of seats that can be grabbed (seats, or seats x (1 + standby_limit) for the over seat type); null in route mode"
                          },
                          "quota_taken": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Seat-mode boards: pooled seats already taken; null in route mode"
                          },
                          "settled": {
                            "type": "boolean",
                            "description": "True once the dispatcher has handed out the vehicles (seat mode)"
                          },
                          "my_bidding": {
                            "type": "integer",
                            "description": "Number of my live bids on this board"
                          },
                          "bid_count": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Bid mode: number of live bids on the board; null otherwise"
                          },
                          "bid_visibility": {
                            "type": "string",
                            "nullable": true,
                            "enum": [
                              "open",
                              "sealed"
                            ]
                          },
                          "currency": {
                            "type": "string",
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Successful",
                  "data": [
                    {
                      "id": 12,
                      "title": "Route Board 2026-03-04",
                      "date": "2026-03-04",
                      "mode": "route",
                      "status": "open",
                      "opens_at": "2026-03-03T18:00:00+00:00",
                      "closes_at": "2026-03-04T05:00:00+00:00",
                      "is_open": true,
                      "seats": 8,
                      "open_seats": 3,
                      "standby_limit": 2,
                      "withdraw_policy": "until_cutoff",
                      "withdraw_cutoff_hours": 12,
                      "my_primary": 1,
                      "my_standby": 0,
                      "my_pooled": 0,
                      "capacity": null,
                      "quota_taken": null,
                      "settled": false
                    },
                    {
                      "id": 13,
                      "title": "Saturday pool",
                      "date": "2026-03-07",
                      "mode": "seat",
                      "status": "open",
                      "opens_at": "2026-03-06T18:00:00+00:00",
                      "closes_at": "2026-03-07T05:00:00+00:00",
                      "is_open": true,
                      "seats": 6,
                      "open_seats": 6,
                      "standby_limit": 1,
                      "withdraw_policy": "allowed",
                      "withdraw_cutoff_hours": null,
                      "my_primary": 0,
                      "my_standby": 0,
                      "my_pooled": 1,
                      "capacity": 12,
                      "quota_taken": 7,
                      "settled": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.boards.get",
        "x-capability": "driver.board",
        "x-graphql": "driverRouteBoards",
        "operationId": "driverRouteBoards"
      }
    },
    "/app/v1/driver/boards/{id}": {
      "get": {
        "tags": [
          "Driver Route Board"
        ],
        "summary": "Get one Route Board with its seats",
        "description": "The board as this driver sees it: every seat with the queue length, the driver's own claim, whether the driver can claim right now and, if not, why (blocked_reason). A board of another pool answers 404. On a seat-mode (\"Grab a Seat\") board data.board.quota describes the pool (capacity, taken, remaining, the caller's pooled claim and whether it can grab now); the seats are then a read-only preview (claimable false, blocked_reason \"seat_mode\") because vehicles are handed out by the dispatcher when the board closes. Driver apps only; needs driver.board on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "description": "The board ID"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "board": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "title": {
                              "type": "string"
                            },
                            "date": {
                              "type": "string",
                              "format": "date"
                            },
                            "mode": {
                              "type": "string",
                              "enum": [
                                "route",
                                "seat",
                                "bid"
                              ]
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "scheduled",
                                "open",
                                "filled",
                                "closed"
                              ]
                            },
                            "opens_at": {
                              "type": "string",
                              "nullable": true
                            },
                            "closes_at": {
                              "type": "string",
                              "nullable": true
                            },
                            "is_open": {
                              "type": "boolean"
                            },
                            "seats": {
                              "type": "integer"
                            },
                            "open_seats": {
                              "type": "integer"
                            },
                            "standby_limit": {
                              "type": "integer"
                            },
                            "withdraw_policy": {
                              "type": "string",
                              "enum": [
                                "allowed",
                                "denied",
                                "until_cutoff"
                              ]
                            },
                            "withdraw_cutoff_hours": {
                              "type": "integer",
                              "nullable": true
                            },
                            "my_primary": {
                              "type": "integer"
                            },
                            "my_standby": {
                              "type": "integer"
                            },
                            "max_primary_per_driver": {
                              "type": "integer"
                            },
                            "quota": {
                              "type": "object",
                              "nullable": true,
                              "description": "Seat-mode boards only; null in route mode",
                              "properties": {
                                "seat_type": {
                                  "type": "string",
                                  "enum": [
                                    "exact",
                                    "over"
                                  ],
                                  "description": "exact = one seat per vehicle; over = seats plus standby places"
                                },
                                "standby_scope": {
                                  "type": "string",
                                  "enum": [
                                    "global",
                                    "per_seat"
                                  ]
                                },
                                "capacity": {
                                  "type": "integer"
                                },
                                "taken": {
                                  "type": "integer"
                                },
                                "remaining": {
                                  "type": "integer"
                                },
                                "seats": {
                                  "type": "integer",
                                  "description": "Vehicles on the board"
                                },
                                "settled": {
                                  "type": "boolean"
                                },
                                "my_claim": {
                                  "type": "object",
                                  "nullable": true,
                                  "description": "The caller's pooled / global-standby claim (same shape as a claim row)"
                                },
                                "claimable": {
                                  "type": "boolean"
                                },
                                "blocked_reason": {
                                  "type": "string",
                                  "nullable": true,
                                  "enum": [
                                    "full",
                                    "settled",
                                    "not_open"
                                  ]
                                }
                              }
                            },
                            "bid_visibility": {
                              "type": "string",
                              "nullable": true,
                              "enum": [
                                "open",
                                "sealed"
                              ],
                              "description": "Bid mode only"
                            },
                            "award_method": {
                              "type": "string",
                              "nullable": true,
                              "enum": [
                                "lowest",
                                "manual"
                              ],
                              "description": "Bid mode only"
                            },
                            "currency": {
                              "type": "string",
                              "nullable": true,
                              "example": "CAD"
                            },
                            "settled": {
                              "type": "boolean"
                            }
                          }
                        },
                        "seats": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "seat_id": {
                                "type": "integer"
                              },
                              "route_id": {
                                "type": "integer"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "open",
                                  "filled",
                                  "locked"
                                ]
                              },
                              "snapshot": {
                                "type": "object",
                                "description": "Publish-time display snapshot of the vehicle slot. start/end/stops are omitted while the board masks previews.",
                                "properties": {
                                  "route_name": {
                                    "type": "string"
                                  },
                                  "date": {
                                    "type": "string"
                                  },
                                  "work_from": {
                                    "type": "string"
                                  },
                                  "work_end": {
                                    "type": "string"
                                  },
                                  "vehicle_type": {
                                    "type": "string",
                                    "nullable": true
                                  },
                                  "distance": {
                                    "type": "number",
                                    "nullable": true
                                  },
                                  "stops": {
                                    "type": "integer",
                                    "nullable": true
                                  },
                                  "start": {
                                    "type": "string",
                                    "nullable": true
                                  },
                                  "end": {
                                    "type": "string",
                                    "nullable": true
                                  }
                                }
                              },
                              "primary_taken": {
                                "type": "boolean"
                              },
                              "standby_taken": {
                                "type": "integer"
                              },
                              "standby_limit": {
                                "type": "integer"
                              },
                              "next_rank": {
                                "type": "integer",
                                "nullable": true,
                                "description": "Rank the caller would get by claiming now; null when full"
                              },
                              "my_claim": {
                                "type": "object",
                                "properties": {
                                  "claim_id": {
                                    "type": "integer"
                                  },
                                  "board_id": {
                                    "type": "integer"
                                  },
                                  "board_title": {
                                    "type": "string"
                                  },
                                  "seat_id": {
                                    "type": "integer",
                                    "nullable": true
                                  },
                                  "route_id": {
                                    "type": "integer"
                                  },
                                  "route_name": {
                                    "type": "string"
                                  },
                                  "date": {
                                    "type": "string"
                                  },
                                  "work_from": {
                                    "type": "string",
                                    "nullable": true
                                  },
                                  "work_end": {
                                    "type": "string",
                                    "nullable": true
                                  },
                                  "rank": {
                                    "type": "integer",
                                    "description": "1 = driver, 2.. = standby position + 1"
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "pooled",
                                      "primary",
                                      "standby",
                                      "withdrawn",
                                      "vetoed",
                                      "replaced",
                                      "displaced",
                                      "skipped",
                                      "expired",
                                      "completed",
                                      "bidding",
                                      "lost"
                                    ]
                                  },
                                  "is_active": {
                                    "type": "boolean"
                                  },
                                  "reason": {
                                    "type": "string",
                                    "nullable": true
                                  },
                                  "claimed_at": {
                                    "type": "string"
                                  },
                                  "decided_at": {
                                    "type": "string",
                                    "nullable": true
                                  },
                                  "can_withdraw": {
                                    "type": "boolean"
                                  },
                                  "withdraw_blocker": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "Lang key explaining why withdrawing is refused"
                                  },
                                  "withdraw_deadline": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "Y-m-d H:i, only for a primary claim under the until_cutoff policy"
                                  },
                                  "is_pooled": {
                                    "type": "boolean",
                                    "description": "True for a seat-mode pooled claim (no vehicle yet)"
                                  },
                                  "global_standby": {
                                    "type": "boolean",
                                    "description": "True for a standby claim that waits for any vehicle (seat mode, global standby scope)"
                                  },
                                  "is_bid": {
                                    "type": "boolean",
                                    "description": "True while the claim is a live bid (status bidding) on a bid-mode board"
                                  },
                                  "bid_price": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Bid mode: the price the driver named"
                                  },
                                  "awarded_price": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Bid mode: the price the route was awarded at (primary claims)"
                                  },
                                  "currency": {
                                    "type": "string",
                                    "nullable": true,
                                    "example": "CAD"
                                  }
                                },
                                "nullable": true
                              },
                              "claimable": {
                                "type": "boolean"
                              },
                              "blocked_reason": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "time_conflict",
                                  "max_primary",
                                  "full",
                                  "locked",
                                  "not_open",
                                  "seat_mode",
                                  "bid_mode"
                                ],
                                "description": "Why the caller cannot claim this seat right now; seat_mode = read-only preview on a Grab-a-Seat board; bid_mode = the seat is auctioned, use POST /v1/driver/boards/{id}/bid"
                              },
                              "bid": {
                                "type": "object",
                                "nullable": true,
                                "description": "Bid mode only (null on route / seat boards): the reverse-auction state of this seat for the caller.",
                                "properties": {
                                  "visibility": {
                                    "type": "string",
                                    "enum": [
                                      "open",
                                      "sealed"
                                    ],
                                    "description": "open = the current lowest bid (not who) is shown; sealed = only the bid count"
                                  },
                                  "currency": {
                                    "type": "string",
                                    "nullable": true,
                                    "example": "CAD"
                                  },
                                  "reference_price": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "The dispatcher's reference pay for this route"
                                  },
                                  "ceiling_price": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Highest accepted bid; a bid above it is refused (422)"
                                  },
                                  "instant_price": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "A bid at or under this price wins the route immediately"
                                  },
                                  "bid_count": {
                                    "type": "integer"
                                  },
                                  "lowest": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Current lowest bid; only on open boards, null when sealed or no bids"
                                  },
                                  "my_bid": {
                                    "type": "number",
                                    "nullable": true
                                  },
                                  "my_claim_id": {
                                    "type": "integer",
                                    "nullable": true
                                  },
                                  "my_position": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "1 = my bid is the lowest; only on open boards"
                                  },
                                  "allow_rebid": {
                                    "type": "boolean",
                                    "description": "Whether a placed bid may be lowered again"
                                  },
                                  "min_bid_step": {
                                    "type": "number",
                                    "description": "A lowered bid must be at least this much under the previous one"
                                  },
                                  "can_bid": {
                                    "type": "boolean"
                                  },
                                  "blocked_reason": {
                                    "type": "string",
                                    "nullable": true,
                                    "enum": [
                                      "settled",
                                      "not_open",
                                      "awarded",
                                      "rebid_denied"
                                    ]
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Successful",
                  "data": {
                    "board": {
                      "id": 12,
                      "title": "Route Board 2026-03-04",
                      "date": "2026-03-04",
                      "mode": "route",
                      "status": "open",
                      "is_open": true,
                      "opens_at": "2026-03-03T18:00:00+00:00",
                      "closes_at": "2026-03-04T05:00:00+00:00",
                      "standby_limit": 2,
                      "withdraw_policy": "until_cutoff",
                      "withdraw_cutoff_hours": 12,
                      "max_primary_per_driver": 1,
                      "my_primary": 0,
                      "quota": null
                    },
                    "seats": [
                      {
                        "seat_id": 41,
                        "route_id": 9001,
                        "status": "open",
                        "snapshot": {
                          "route_name": "East-3",
                          "date": "2026-03-04",
                          "work_from": "07:00",
                          "work_end": "15:00",
                          "vehicle_type": "Van",
                          "distance": 68,
                          "stops": 42,
                          "start": "Scarborough",
                          "end": "Markham"
                        },
                        "primary_taken": false,
                        "standby_taken": 0,
                        "standby_limit": 2,
                        "next_rank": 1,
                        "my_claim": null,
                        "claimable": true,
                        "blocked_reason": null
                      },
                      {
                        "seat_id": 42,
                        "route_id": 9002,
                        "status": "filled",
                        "snapshot": {
                          "route_name": "East-5",
                          "date": "2026-03-04",
                          "work_from": "07:30",
                          "work_end": "15:30",
                          "vehicle_type": "Van",
                          "distance": 55,
                          "stops": 38,
                          "start": "Scarborough",
                          "end": "Markham"
                        },
                        "primary_taken": true,
                        "standby_taken": 1,
                        "standby_limit": 2,
                        "next_rank": 3,
                        "my_claim": null,
                        "claimable": true,
                        "blocked_reason": null
                      },
                      {
                        "seat_id": 43,
                        "route_id": 9003,
                        "status": "open",
                        "snapshot": {
                          "route_name": "North-1",
                          "date": "2026-03-04",
                          "work_from": "06:30",
                          "work_end": "14:30",
                          "vehicle_type": "Van",
                          "distance": 68,
                          "stops": 42,
                          "start": "Scarborough",
                          "end": "Markham"
                        },
                        "primary_taken": false,
                        "standby_taken": 0,
                        "standby_limit": 2,
                        "next_rank": 1,
                        "my_claim": null,
                        "claimable": false,
                        "blocked_reason": "time_conflict"
                      }
                    ]
                  }
                },
                "examples": {
                  "route_mode": {
                    "summary": "Pick a Route board",
                    "value": {
                      "result": true,
                      "message": "Successful",
                      "data": {
                        "board": {
                          "id": 12,
                          "title": "Route Board 2026-03-04",
                          "date": "2026-03-04",
                          "mode": "route",
                          "status": "open",
                          "is_open": true,
                          "opens_at": "2026-03-03T18:00:00+00:00",
                          "closes_at": "2026-03-04T05:00:00+00:00",
                          "standby_limit": 2,
                          "withdraw_policy": "until_cutoff",
                          "withdraw_cutoff_hours": 12,
                          "max_primary_per_driver": 1,
                          "my_primary": 0,
                          "quota": null
                        },
                        "seats": [
                          {
                            "seat_id": 41,
                            "route_id": 9001,
                            "status": "open",
                            "snapshot": {
                              "route_name": "East-3",
                              "date": "2026-03-04",
                              "work_from": "07:00",
                              "work_end": "15:00",
                              "vehicle_type": "Van",
                              "distance": 68,
                              "stops": 42,
                              "start": "Scarborough",
                              "end": "Markham"
                            },
                            "primary_taken": false,
                            "standby_taken": 0,
                            "standby_limit": 2,
                            "next_rank": 1,
                            "my_claim": null,
                            "claimable": true,
                            "blocked_reason": null
                          },
                          {
                            "seat_id": 42,
                            "route_id": 9002,
                            "status": "filled",
                            "snapshot": {
                              "route_name": "East-5",
                              "date": "2026-03-04",
                              "work_from": "07:30",
                              "work_end": "15:30",
                              "vehicle_type": "Van",
                              "distance": 55,
                              "stops": 38,
                              "start": "Scarborough",
                              "end": "Markham"
                            },
                            "primary_taken": true,
                            "standby_taken": 1,
                            "standby_limit": 2,
                            "next_rank": 3,
                            "my_claim": null,
                            "claimable": true,
                            "blocked_reason": null
                          },
                          {
                            "seat_id": 43,
                            "route_id": 9003,
                            "status": "open",
                            "snapshot": {
                              "route_name": "North-1",
                              "date": "2026-03-04",
                              "work_from": "06:30",
                              "work_end": "14:30",
                              "vehicle_type": "Van",
                              "distance": 68,
                              "stops": 42,
                              "start": "Scarborough",
                              "end": "Markham"
                            },
                            "primary_taken": false,
                            "standby_taken": 0,
                            "standby_limit": 2,
                            "next_rank": 1,
                            "my_claim": null,
                            "claimable": false,
                            "blocked_reason": "time_conflict"
                          }
                        ]
                      }
                    }
                  },
                  "seat_mode": {
                    "summary": "Grab a Seat board",
                    "value": {
                      "result": true,
                      "message": "Successful",
                      "data": {
                        "board": {
                          "id": 13,
                          "title": "Saturday pool",
                          "date": "2026-03-07",
                          "mode": "seat",
                          "status": "open",
                          "is_open": true,
                          "quota": {
                            "seat_type": "over",
                            "standby_scope": "global",
                            "capacity": 12,
                            "taken": 7,
                            "remaining": 5,
                            "seats": 6,
                            "settled": false,
                            "my_claim": null,
                            "claimable": true,
                            "blocked_reason": null
                          },
                          "opens_at": "2026-03-06T18:00:00+00:00",
                          "closes_at": "2026-03-07T05:00:00+00:00",
                          "standby_limit": 1,
                          "withdraw_policy": "allowed",
                          "withdraw_cutoff_hours": null,
                          "max_primary_per_driver": 1,
                          "my_primary": 0
                        },
                        "seats": [
                          {
                            "seat_id": 61,
                            "route_id": 9101,
                            "status": "open",
                            "snapshot": {
                              "route_name": "East-3",
                              "date": "2026-03-07",
                              "work_from": "07:00",
                              "work_end": "15:00",
                              "vehicle_type": "Van",
                              "distance": 68,
                              "stops": 42
                            },
                            "primary_taken": false,
                            "standby_taken": 0,
                            "standby_limit": 1,
                            "next_rank": 1,
                            "my_claim": null,
                            "claimable": false,
                            "blocked_reason": "seat_mode"
                          }
                        ]
                      }
                    }
                  },
                  "bid_mode": {
                    "summary": "Bid mode (reverse auction)",
                    "value": {
                      "result": true,
                      "message": "Successful",
                      "data": {
                        "board": {
                          "id": 14,
                          "title": "Friday auction",
                          "date": "2026-03-06",
                          "mode": "bid",
                          "status": "open",
                          "is_open": true,
                          "quota": null,
                          "bid_visibility": "open",
                          "award_method": "lowest",
                          "currency": "CAD",
                          "settled": false,
                          "opens_at": "2026-03-05T18:00:00+00:00",
                          "closes_at": "2026-03-06T05:00:00+00:00",
                          "standby_limit": 1,
                          "withdraw_policy": "allowed",
                          "withdraw_cutoff_hours": null,
                          "max_primary_per_driver": 1,
                          "my_primary": 0
                        },
                        "seats": [
                          {
                            "seat_id": 61,
                            "route_id": 9010,
                            "status": "open",
                            "snapshot": {
                              "route_name": "West-2",
                              "date": "2026-03-06",
                              "work_from": "07:00",
                              "work_end": "15:00",
                              "vehicle_type": "Van",
                              "distance": 68,
                              "stops": 42,
                              "start": "Scarborough",
                              "end": "Markham"
                            },
                            "primary_taken": false,
                            "standby_taken": 0,
                            "standby_limit": 1,
                            "next_rank": 1,
                            "my_claim": {
                              "claim_id": 702,
                              "board_id": 14,
                              "board_title": "Friday auction",
                              "seat_id": 61,
                              "route_id": 9010,
                              "route_name": "West-2",
                              "is_pooled": false,
                              "is_bid": true,
                              "bid_price": 290,
                              "awarded_price": null,
                              "currency": "CAD",
                              "global_standby": false,
                              "date": "2026-03-06",
                              "work_from": "07:00",
                              "work_end": "15:00",
                              "rank": 0,
                              "status": "bidding",
                              "is_active": true,
                              "reason": null,
                              "claimed_at": "2026-03-05 20:11:02",
                              "decided_at": null,
                              "can_withdraw": true,
                              "withdraw_blocker": null,
                              "withdraw_deadline": null
                            },
                            "bid": {
                              "visibility": "open",
                              "currency": "CAD",
                              "reference_price": 300,
                              "ceiling_price": 350,
                              "instant_price": 200,
                              "bid_count": 3,
                              "lowest": 285,
                              "my_bid": 290,
                              "my_claim_id": 702,
                              "my_position": 2,
                              "allow_rebid": true,
                              "min_bid_step": 5,
                              "can_bid": true,
                              "blocked_reason": null
                            },
                            "claimable": false,
                            "blocked_reason": "bid_mode"
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "404": {
            "description": "Board not found or not visible to this driver",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "Board not found."
                }
              }
            }
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.boards.id.get",
        "x-capability": "driver.board",
        "x-graphql": "driverRouteBoard",
        "operationId": "driverRouteBoard"
      }
    },
    "/app/v1/driver/boards/{id}/claim": {
      "post": {
        "tags": [
          "Driver Route Board"
        ],
        "summary": "Claim a seat (route) on a Route Board, or grab a seat on a seat-mode board",
        "description": "Route mode (seat_id required): first come first served. Rank 1 becomes the driver and is put on the vehicle slot immediately; later ranks queue as standby up to the board's standby_limit. Seat mode (\"Grab a Seat\", seat_id optional and ignored): the driver takes the next numbered seat in the board's pool (status pooled, data.capacity = pool size); the dispatcher hands out the vehicles when the board closes. Throttled to 30 requests per minute per user. 409 when the seat is full, already claimed by you, the board is not open, the seat is no longer available, the pool is full or the board is already settled; 422 for a time conflict, the per-driver maximum, eligibility or a bad seat_id (route mode only). Driver apps only; needs driver.board on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "description": "The board ID"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "seat_id": {
                    "type": "integer",
                    "description": "The seat ID on that board. Required in route mode; optional and ignored on a seat-mode board."
                  }
                }
              },
              "example": {
                "seat_id": 41
              },
              "examples": {
                "route_mode": {
                  "summary": "Route mode",
                  "value": {
                    "seat_id": 41
                  }
                },
                "seat_mode": {
                  "summary": "Seat mode (body may be empty)",
                  "value": {}
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rank": {
                          "type": "integer"
                        },
                        "claim_id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "primary",
                            "standby",
                            "pooled"
                          ]
                        },
                        "capacity": {
                          "type": "integer",
                          "description": "Seat mode only: size of the pool the seat was taken from"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "You got this route. It is now in your route list.",
                  "data": {
                    "rank": 1,
                    "claim_id": 501,
                    "status": "primary"
                  }
                },
                "examples": {
                  "route_mode": {
                    "summary": "Route mode",
                    "value": {
                      "result": true,
                      "message": "You got this route. It is now in your route list.",
                      "data": {
                        "rank": 1,
                        "claim_id": 501,
                        "status": "primary"
                      }
                    }
                  },
                  "seat_mode": {
                    "summary": "Seat mode",
                    "value": {
                      "result": true,
                      "message": "You got a seat. Vehicles are handed out when the board closes — we will tell you which one is yours.",
                      "data": {
                        "rank": 8,
                        "claim_id": 612,
                        "status": "pooled",
                        "capacity": 12
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "404": {
            "description": "Board not found or not visible to this driver",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "Board not found."
                }
              }
            }
          },
          "409": {
            "description": "Seat full / already claimed / board not open / seat unavailable / pool full / board settled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "This route is full — the driver and every standby place are taken."
                },
                "examples": {
                  "seat_full": {
                    "value": {
                      "result": false,
                      "message": "This route is full — the driver and every standby place are taken."
                    }
                  },
                  "quota_full": {
                    "value": {
                      "result": false,
                      "message": "All seats on this board are taken."
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Time conflict, per-driver maximum reached, not eligible, or seat not on this board",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "This route overlaps another vehicle you already hold that day."
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.boards.id.claim.post",
        "x-capability": "driver.board",
        "operationId": "driverBoardsIdClaimPost"
      }
    },
    "/app/v1/driver/boards/{id}/bid": {
      "post": {
        "tags": [
          "Driver Route Board"
        ],
        "summary": "Place or lower a bid on a seat of a bid-mode (reverse auction) Route Board",
        "description": "Bid mode only: the driver names the pay they will accept for the route. The lowest bid wins when the board's deadline (closes_at) passes; a bid at or under the seat's instant_price wins immediately (data.awarded = true, the driver is put on the vehicle slot at once). A second bid from the same driver is a revision: it must be lower than the current one by at least the board's min_bid_step, and only when the board allows rebids. On an open board data.lowest is the current lowest bid on the seat (not who); on a sealed board it is null. A new lowest bid inside the anti-snipe window pushes the deadline out — data.closes_at is always the deadline that applies after this bid. Throttled to 30 requests per minute per user. 409 when the board is not open, already settled, the seat is no longer available (awarded) or the board does not allow rebids; 422 for a bid above the ceiling, a revised bid that is not lower by min_bid_step, a non-positive price, a seat that is not on this board, a board that is not in bid mode, or an ineligible driver. Driver apps only; needs driver.board on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "description": "The board ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "seat_id",
                  "price"
                ],
                "properties": {
                  "seat_id": {
                    "type": "integer",
                    "description": "The seat ID on that board"
                  },
                  "price": {
                    "type": "number",
                    "description": "The pay the driver will accept for the route, in the board's currency"
                  }
                }
              },
              "example": {
                "seat_id": 61,
                "price": 290
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "claim_id": {
                          "type": "integer"
                        },
                        "price": {
                          "type": "number",
                          "description": "The bid as stored (rounded to 2 decimals)"
                        },
                        "awarded": {
                          "type": "boolean",
                          "description": "True when the bid met the instant price and the route is already the driver's"
                        },
                        "lowest": {
                          "type": "number",
                          "nullable": true,
                          "description": "Current lowest bid on the seat after this bid; null on a sealed board"
                        },
                        "closes_at": {
                          "type": "string",
                          "nullable": true,
                          "description": "ISO 8601 deadline that applies after this bid (may have been extended by anti-snipe)"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "bidding",
                            "primary"
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Your bid is in.",
                  "data": {
                    "claim_id": 702,
                    "price": 290,
                    "awarded": false,
                    "lowest": 285,
                    "closes_at": "2026-03-06T05:00:00+00:00",
                    "status": "bidding"
                  }
                },
                "examples": {
                  "placed": {
                    "summary": "Bid placed (open board)",
                    "value": {
                      "result": true,
                      "message": "Your bid is in.",
                      "data": {
                        "claim_id": 702,
                        "price": 290,
                        "awarded": false,
                        "lowest": 285,
                        "closes_at": "2026-03-06T05:00:00+00:00",
                        "status": "bidding"
                      }
                    }
                  },
                  "lowered": {
                    "summary": "Bid lowered, deadline extended by anti-snipe",
                    "value": {
                      "result": true,
                      "message": "Your bid has been lowered.",
                      "data": {
                        "claim_id": 702,
                        "price": 280,
                        "awarded": false,
                        "lowest": 280,
                        "closes_at": "2026-03-06T05:10:00+00:00",
                        "status": "bidding"
                      }
                    }
                  },
                  "instant": {
                    "summary": "Instant price met",
                    "value": {
                      "result": true,
                      "message": "Your bid met the instant price — the route is yours.",
                      "data": {
                        "claim_id": 702,
                        "price": 200,
                        "awarded": true,
                        "lowest": 200,
                        "closes_at": "2026-03-06T05:00:00+00:00",
                        "status": "primary"
                      }
                    }
                  },
                  "sealed": {
                    "summary": "Sealed board: lowest is never revealed",
                    "value": {
                      "result": true,
                      "message": "Your bid is in.",
                      "data": {
                        "claim_id": 703,
                        "price": 290,
                        "awarded": false,
                        "lowest": null,
                        "closes_at": "2026-03-06T05:00:00+00:00",
                        "status": "bidding"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "404": {
            "description": "Board not found or not visible to this driver",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "Board not found."
                }
              }
            }
          },
          "409": {
            "description": "Board not open / board settled / seat already awarded / rebids not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "This vehicle is no longer available."
                },
                "examples": {
                  "seat_awarded": {
                    "value": {
                      "result": false,
                      "message": "This vehicle is no longer available."
                    }
                  },
                  "rebid_denied": {
                    "value": {
                      "result": false,
                      "message": "Bids cannot be changed on this board."
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Above the ceiling, revised bid not lower by min_bid_step, invalid price, seat not on this board, board not in bid mode, or not eligible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "That is above the highest price accepted for this route."
                },
                "examples": {
                  "over_ceiling": {
                    "value": {
                      "result": false,
                      "message": "That is above the highest price accepted for this route."
                    }
                  },
                  "must_be_lower": {
                    "value": {
                      "result": false,
                      "message": "A revised bid must be lower than your current one by at least the minimum step."
                    }
                  },
                  "invalid": {
                    "value": {
                      "result": false,
                      "message": "Please enter a price above zero."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.boards.id.bid.post",
        "x-capability": "driver.board",
        "operationId": "driverBoardsIdBidPost"
      }
    },
    "/app/v1/driver/claims/{id}/withdraw": {
      "post": {
        "tags": [
          "Driver Route Board"
        ],
        "summary": "Withdraw one of your Route Board claims",
        "description": "Subject to the board's withdraw policy (allowed / denied / until N hours before the route starts). A standby claim may always be left. When a primary withdraws, the next standby is promoted automatically. 403 when the policy refuses; data.withdraw_deadline then tells until when it was possible (null under the denied policy). A pooled seat (seat mode) may always be given up before the board is settled; the seats behind it move up. A live bid (status bidding) on a bid-mode board may always be retracted before the award. Driver apps only; needs driver.board on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "description": "The claim ID"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "nullable": true
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Your claim has been withdrawn.",
                  "data": null
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "404": {
            "description": "Claim not found or not yours",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "Board not found."
                }
              }
            }
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.claims.id.withdraw.post",
        "x-capability": "driver.board",
        "operationId": "driverClaimsIdWithdrawPost"
      }
    },
    "/app/v1/driver/claims": {
      "get": {
        "tags": [
          "Driver Route Board"
        ],
        "summary": "List your Route Board claims",
        "description": "Active claims (pooled / primary / standby) first, then — with history=1 — withdrawn, vetoed, replaced, displaced, skipped, expired and completed ones. Each row says whether it can be withdrawn right now and, for a primary under the until_cutoff policy, the deadline. Driver apps only; needs driver.board on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "query",
            "name": "history",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "required": false,
            "description": "1 to include finished claims (default 0)"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "claim_id": {
                            "type": "integer"
                          },
                          "board_id": {
                            "type": "integer"
                          },
                          "board_title": {
                            "type": "string"
                          },
                          "seat_id": {
                            "type": "integer",
                            "nullable": true
                          },
                          "route_id": {
                            "type": "integer"
                          },
                          "route_name": {
                            "type": "string"
                          },
                          "date": {
                            "type": "string"
                          },
                          "work_from": {
                            "type": "string",
                            "nullable": true
                          },
                          "work_end": {
                            "type": "string",
                            "nullable": true
                          },
                          "rank": {
                            "type": "integer",
                            "description": "Route mode: 1 = driver, 2.. = standby position + 1. Seat mode: the seat number (pooled) or the standby position (global standby)."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pooled",
                              "primary",
                              "standby",
                              "withdrawn",
                              "vetoed",
                              "replaced",
                              "displaced",
                              "skipped",
                              "expired",
                              "completed",
                              "bidding",
                              "lost"
                            ]
                          },
                          "is_active": {
                            "type": "boolean"
                          },
                          "reason": {
                            "type": "string",
                            "nullable": true
                          },
                          "claimed_at": {
                            "type": "string"
                          },
                          "decided_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "can_withdraw": {
                            "type": "boolean"
                          },
                          "withdraw_blocker": {
                            "type": "string",
                            "nullable": true,
                            "description": "Lang key explaining why withdrawing is refused"
                          },
                          "withdraw_deadline": {
                            "type": "string",
                            "nullable": true,
                            "description": "Y-m-d H:i, only for a primary claim under the until_cutoff policy"
                          },
                          "is_pooled": {
                            "type": "boolean",
                            "description": "Seat mode: a numbered seat in the pool, no vehicle yet"
                          },
                          "global_standby": {
                            "type": "boolean",
                            "description": "Seat mode: standby for any vehicle on the board"
                          },
                          "is_bid": {
                            "type": "boolean",
                            "description": "True while the claim is a live bid (status bidding) on a bid-mode board"
                          },
                          "bid_price": {
                            "type": "number",
                            "nullable": true,
                            "description": "Bid mode: the price the driver named"
                          },
                          "awarded_price": {
                            "type": "number",
                            "nullable": true,
                            "description": "Bid mode: the price the route was awarded at (primary claims)"
                          },
                          "currency": {
                            "type": "string",
                            "nullable": true,
                            "example": "CAD"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Successful",
                  "data": [
                    {
                      "claim_id": 501,
                      "board_id": 12,
                      "board_title": "Route Board 2026-03-04",
                      "seat_id": 41,
                      "route_id": 9001,
                      "route_name": "East-3",
                      "date": "2026-03-04",
                      "work_from": "07:00",
                      "work_end": "15:00",
                      "rank": 1,
                      "status": "primary",
                      "is_active": true,
                      "reason": null,
                      "claimed_at": "2026-03-03 18:00:07",
                      "decided_at": null,
                      "can_withdraw": true,
                      "withdraw_blocker": null,
                      "withdraw_deadline": "2026-03-03 19:00",
                      "is_pooled": false,
                      "global_standby": false
                    },
                    {
                      "claim_id": 612,
                      "board_id": 13,
                      "board_title": "Saturday pool",
                      "seat_id": null,
                      "route_id": 0,
                      "route_name": "",
                      "is_pooled": true,
                      "global_standby": false,
                      "date": "2026-03-07",
                      "work_from": null,
                      "work_end": null,
                      "rank": 8,
                      "status": "pooled",
                      "is_active": true,
                      "reason": null,
                      "claimed_at": "2026-03-06 18:00:03",
                      "decided_at": null,
                      "can_withdraw": true,
                      "withdraw_blocker": null,
                      "withdraw_deadline": null
                    },
                    {
                      "claim_id": 502,
                      "board_id": 12,
                      "board_title": "Route Board 2026-03-04",
                      "seat_id": 42,
                      "route_id": 9002,
                      "route_name": "East-5",
                      "date": "2026-03-04",
                      "work_from": "07:30",
                      "work_end": "15:30",
                      "rank": 2,
                      "status": "standby",
                      "is_active": true,
                      "reason": null,
                      "claimed_at": "2026-03-03 18:00:07",
                      "decided_at": null,
                      "can_withdraw": true,
                      "withdraw_blocker": null,
                      "withdraw_deadline": null,
                      "is_pooled": false,
                      "global_standby": false
                    },
                    {
                      "claim_id": 477,
                      "board_id": 11,
                      "board_title": "Route Board 2026-03-02",
                      "seat_id": 41,
                      "route_id": 9001,
                      "route_name": "West-2",
                      "date": "2026-03-02",
                      "work_from": "07:00",
                      "work_end": "15:00",
                      "rank": 1,
                      "status": "replaced",
                      "is_active": false,
                      "reason": "Assigned to another driver",
                      "claimed_at": "2026-03-03 18:00:07",
                      "decided_at": "2026-03-02 14:20:11",
                      "can_withdraw": false,
                      "withdraw_blocker": "route_board.err_claim_not_active",
                      "withdraw_deadline": null,
                      "is_pooled": false,
                      "global_standby": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.claims.get",
        "x-capability": "driver.board",
        "operationId": "driverClaimsGet"
      }
    },
    "/app/v1/driver/routes/cancel": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Cancel route by driver",
        "description": "Allows a driver to cancel their own assigned route. Requires business setting 'Allow Cancel Route By Driver' to be enabled. If the route has only one driver, the entire route will be cancelled. If the route has multiple drivers, only this driver's orders will be cancelled. Driver apps only; needs driver.route_edit on the token. Answered exactly as the internal driver route.",
        "operationId": "cancelRouteByDriver",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "route_id"
                ],
                "properties": {
                  "route_id": {
                    "type": "integer",
                    "description": "ID of the route to cancel",
                    "example": 123
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Route cancelled successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Route cancelled successfully"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Route ID is required or cancellation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "string",
                      "example": "Route ID is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "404": {
            "description": "Not Found - Route does not exist",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "string",
                      "example": "Route not found"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.routes.cancel.post",
        "x-capability": "driver.route_edit",
        "x-graphql": "driverCancelRoute"
      }
    },
    "/app/v1/driver/startDelivery": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "start Delivery By route id",
        "description": "Starts the route by its id. A route of up to 200 stops (START_DELIVERY_SYNC_ORDERS) starts wholly before the answer. On a larger route the first 200 stops in stop order start before the answer and the rest start right after it in the background, a chunk at a time, with the same tracking events, notifications and stock-outs, normally within seconds and at most about a minute later. A stop the driver delivers, fails or picks up before its chunk starts is left as it is, and once the run is ended the remaining stops are not started; the answer is unchanged. With the load gate (clients with warehouse management): 400 while an outbound order travelling on the run is still being picked; message names the outbound numbers (driver_api routes.start_route_outbound_not_ready), the same shape as the strict start refusal. Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteStatusUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message": "Success"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.startDelivery.post",
        "x-capability": "driver.routes",
        "x-graphql": "driverStartDelivery",
        "operationId": "driverStartDelivery"
      }
    },
    "/app/v1/driver/endDelivery": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "end Delivery By route id",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteStatusUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message": "Success"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.endDelivery.post",
        "x-capability": "driver.routes",
        "x-graphql": "driverEndDelivery",
        "description": "Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route.",
        "operationId": "driverEndDelivery"
      }
    },
    "/app/v1/driver/routes/{routeId}/orders": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get orders on route for one driver",
        "parameters": [
          {
            "in": "path",
            "name": "routeId",
            "schema": {
              "type": "integer"
            },
            "required": true
          },
          {
            "in": "query",
            "name": "ids",
            "schema": {
              "type": "string"
            },
            "required": false
          },
          {
            "in": "query",
            "name": "isHideSuccess",
            "schema": {
              "type": "integer"
            },
            "required": false
          },
          {
            "in": "query",
            "name": "statusType",
            "schema": {
              "type": "string",
              "enum": [
                "delivering",
                "failed",
                "success"
              ]
            },
            "required": false,
            "description": "Optional tab filter. failed also lists stops the warehouse took back (stop_outcome_code=returned_to_warehouse)."
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "type": {
                        "type": "string"
                      },
                      "order_type": {
                        "type": "string"
                      },
                      "is_p2p": {
                        "type": "integer"
                      },
                      "is_locked": {
                        "type": "integer"
                      },
                      "scan_count": {
                        "type": "integer",
                        "description": "Driver loading scans on this stop (driver app only)."
                      },
                      "sorting_scan_count": {
                        "type": "integer",
                        "description": "Depot sorting scans on this stop (sorting pages, shipping API, warehouse app). Added additively; 0 when never sorted."
                      },
                      "ref": {
                        "type": "string"
                      },
                      "carrier_name": {
                        "type": "string"
                      },
                      "business_name": {
                        "type": "string"
                      },
                      "address_1": {
                        "type": "string"
                      },
                      "address_2": {
                        "type": "string"
                      },
                      "address_type": {
                        "type": "string"
                      },
                      "signature_option": {
                        "type": "integer"
                      },
                      "city": {
                        "type": "string"
                      },
                      "province": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string"
                      },
                      "postcode": {
                        "type": "string"
                      },
                      "buzz_code": {
                        "type": "string"
                      },
                      "latitude": {
                        "type": "string"
                      },
                      "longitude": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string",
                        "nullable": true
                      },
                      "telephone": {
                        "type": "string",
                        "nullable": true
                      },
                      "tracking_number": {
                        "type": "string"
                      },
                      "external_tracking_number": {
                        "type": "string"
                      },
                      "note": {
                        "type": "string"
                      },
                      "driver_alias": {
                        "type": "string"
                      },
                      "stop_number": {
                        "type": "integer"
                      },
                      "driver_id": {
                        "type": "integer"
                      },
                      "leg_number": {
                        "type": "string",
                        "nullable": true,
                        "description": "Number of the driver's leg of this route: the fleet code followed by a sequence (\"ACME-2\"), or \"L-<n>\" when the fleet has no code, numbered across the whole route. Assigned on first read and then kept. Additive; null before a number exists."
                      },
                      "status": {
                        "type": "string"
                      },
                      "packages": {
                        "type": "integer"
                      },
                      "notification_language": {
                        "type": "string"
                      },
                      "return_reason_id": {
                        "type": "string",
                        "nullable": true
                      },
                      "orders_status_id": {
                        "type": "integer"
                      },
                      "current_route_id": {
                        "type": "integer"
                      },
                      "related_order_type": {
                        "type": "integer",
                        "nullable": true
                      },
                      "related_order_id": {
                        "type": "integer",
                        "nullable": true
                      },
                      "allow_dropoff": {
                        "type": "integer"
                      },
                      "created_at": {
                        "type": "string"
                      },
                      "driverNotes": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "files": {
                        "type": "object",
                        "properties": {
                          "photo_urls": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "signature_urls": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      },
                      "is_finished": {
                        "type": "integer"
                      },
                      "is_postponed": {
                        "type": "integer"
                      },
                      "full_address": {
                        "type": "string"
                      },
                      "operation_mode": {
                        "type": "integer"
                      },
                      "is_multiple": {
                        "type": "integer"
                      },
                      "total_orders": {
                        "type": "integer"
                      },
                      "current_order": {
                        "type": "integer"
                      },
                      "is_recurring_pickup": {
                        "type": "boolean",
                        "description": "A mandatory recurring pickup stop"
                      },
                      "can_hand_off": {
                        "type": "boolean",
                        "description": "The driver may hand this stop off: the route allows hand-off and the stop is not a mandatory recurring pickup"
                      },
                      "stop_outcome_code": {
                        "type": "string",
                        "nullable": true,
                        "description": "Added additively. Present when the list includes failed stops (no statusType, or statusType=failed): returned_to_warehouse when the warehouse took the parcel back while the stop was open (the stop is failed and keeps its number), otherwise null."
                      },
                      "stop_outcome_text": {
                        "type": "string",
                        "nullable": true,
                        "description": "Added additively. Wording of stop_outcome_code in the request language; null when stop_outcome_code is null."
                      }
                    }
                  }
                },
                "example": [
                  {
                    "id": 299545,
                    "type": "P",
                    "order_type": "P2P",
                    "is_p2p": 1,
                    "is_locked": 0,
                    "ref": "T1",
                    "carrier_name": "DEMO",
                    "business_name": "DEMO",
                    "address_1": "DMEO",
                    "address_2": "",
                    "address_type": "",
                    "signature_option": 0,
                    "city": "Saint-Jerome",
                    "province": "QC",
                    "country": "Canada",
                    "postcode": "J5L0E1",
                    "buzz_code": "",
                    "latitude": "45.797655",
                    "longitude": "-74.049801",
                    "name": "y",
                    "email": null,
                    "telephone": null,
                    "tracking_number": "SR904766214130",
                    "external_tracking_number": "",
                    "note": "",
                    "driver_alias": "pd1",
                    "stop_number": 1,
                    "driver_id": 343,
                    "leg_number": "L-1",
                    "status": "Already Planned",
                    "packages": 1,
                    "notification_language": "en",
                    "return_reason_id": null,
                    "orders_status_id": 5,
                    "current_route_id": 3964,
                    "related_order_type": null,
                    "related_order_id": null,
                    "allow_dropoff": 1,
                    "pin_required": 0,
                    "created_at": "2024-01-15 10:30:00",
                    "driverNotes": [],
                    "files": {
                      "photo_urls": [],
                      "signature_urls": []
                    },
                    "is_finished": 0,
                    "is_postponed": 0,
                    "full_address": "DEMO,Montreal,QC,H4E3R3",
                    "operation_mode": 0,
                    "is_multiple": 1,
                    "total_orders": 2,
                    "current_order": 2,
                    "is_recurring_pickup": false,
                    "can_hand_off": false
                  },
                  {
                    "id": 299548,
                    "type": "P",
                    "order_type": "P",
                    "is_p2p": 0,
                    "is_locked": 0,
                    "ref": "",
                    "carrier_name": "DEMO",
                    "business_name": "DEMO",
                    "address_1": "DEMO",
                    "address_2": "",
                    "city": "Saint-Jerome",
                    "province": "QC",
                    "country": "Canada",
                    "postcode": "J5L0E1",
                    "buzz_code": "",
                    "latitude": "45.797655",
                    "longitude": "-74.049801",
                    "name": "X",
                    "email": "",
                    "telephone": "",
                    "tracking_number": "SR270017412103",
                    "external_tracking_number": "",
                    "note": "",
                    "driver_alias": "pd1",
                    "stop_number": 2,
                    "driver_id": 343,
                    "leg_number": "L-1",
                    "status": "Already Planned",
                    "packages": 1,
                    "notification_language": "en",
                    "return_reason_id": null,
                    "orders_status_id": 5,
                    "current_route_id": 3964,
                    "allow_dropoff": 1,
                    "pin_required": 0,
                    "created_at": "2024-01-15 11:00:00",
                    "driverNotes": [],
                    "files": {
                      "photo_urls": [],
                      "signature_urls": []
                    },
                    "is_finished": 0,
                    "is_postponed": 0,
                    "full_address": "DEMO,Saint-Jerome,QC,J5L0E1",
                    "operation_mode": 0,
                    "is_multiple": 1,
                    "total_orders": 3,
                    "current_order": 1,
                    "is_recurring_pickup": false,
                    "can_hand_off": false
                  },
                  {
                    "id": 299546,
                    "type": "D",
                    "order_type": "D",
                    "is_p2p": 0,
                    "is_locked": 0,
                    "ref": "1231",
                    "carrier_name": "DEMO",
                    "business_name": "DEMO",
                    "address_1": "DEMO",
                    "address_2": "",
                    "city": "Saint-Jerome",
                    "province": "QC",
                    "country": "Canada",
                    "postcode": "J5L0E1",
                    "buzz_code": "",
                    "latitude": "45.797655",
                    "longitude": "-74.049801",
                    "name": "",
                    "email": "",
                    "telephone": "",
                    "tracking_number": "SR662910478770",
                    "external_tracking_number": "",
                    "note": "",
                    "driver_alias": "pd1",
                    "stop_number": 3,
                    "driver_id": 343,
                    "leg_number": "L-1",
                    "status": "Already Planned",
                    "packages": 1,
                    "notification_language": "en",
                    "return_reason_id": null,
                    "orders_status_id": 5,
                    "current_route_id": 3964,
                    "allow_dropoff": 1,
                    "pin_required": 1,
                    "created_at": "2024-01-15 11:30:00",
                    "driverNotes": [],
                    "files": {
                      "photo_urls": [],
                      "signature_urls": []
                    },
                    "is_finished": 0,
                    "is_postponed": 0,
                    "full_address": "DEMO,Saint-Jerome,QC,J5L0E1",
                    "operation_mode": 0,
                    "is_multiple": 1,
                    "total_orders": 3,
                    "current_order": 2,
                    "is_recurring_pickup": false,
                    "can_hand_off": false
                  },
                  {
                    "id": 299547,
                    "type": "P",
                    "order_type": "D",
                    "is_p2p": 0,
                    "is_locked": 0,
                    "ref": "123",
                    "carrier_name": "DEMO",
                    "business_name": "DEMO",
                    "address_1": "DEMO",
                    "address_2": "",
                    "city": "Montreal",
                    "province": "QC",
                    "country": "Canada",
                    "postcode": "H4E3R3",
                    "buzz_code": "",
                    "latitude": "45.452116",
                    "longitude": "-73.591895",
                    "name": "X",
                    "email": null,
                    "telephone": null,
                    "tracking_number": "SR329762240553",
                    "external_tracking_number": "",
                    "note": "",
                    "driver_alias": "pd1",
                    "stop_number": 4,
                    "driver_id": 343,
                    "leg_number": "L-1",
                    "status": "Already Planned",
                    "packages": 1,
                    "notification_language": "en",
                    "return_reason_id": null,
                    "orders_status_id": 5,
                    "current_route_id": 3964,
                    "allow_dropoff": 1,
                    "pin_required": 0,
                    "created_at": "2024-01-15 12:00:00",
                    "driverNotes": [],
                    "files": {
                      "photo_urls": [],
                      "signature_urls": []
                    },
                    "is_finished": 0,
                    "is_postponed": 0,
                    "full_address": "DEMO,Saint-Jerome,QC,J5L0E1",
                    "operation_mode": 0,
                    "is_multiple": 1,
                    "total_orders": 3,
                    "current_order": 3,
                    "is_recurring_pickup": false,
                    "can_hand_off": false
                  },
                  {
                    "id": 299545,
                    "type": "D",
                    "order_type": "P2P",
                    "is_p2p": 1,
                    "is_locked": 1,
                    "ref": "T1",
                    "carrier_name": "DEMO",
                    "business_name": "DEMO",
                    "address_1": "DEMO",
                    "address_2": "",
                    "city": "Montreal",
                    "province": "QC",
                    "country": "Canada",
                    "postcode": "H4E3R3",
                    "buzz_code": "",
                    "latitude": "45.452116",
                    "longitude": "-73.591895",
                    "name": "x",
                    "email": "",
                    "telephone": "",
                    "tracking_number": "SR904766214130",
                    "external_tracking_number": "",
                    "note": "",
                    "driver_alias": "pd1",
                    "stop_number": 5,
                    "driver_id": 343,
                    "leg_number": "L-1",
                    "status": "Already Planned",
                    "packages": 1,
                    "notification_language": "en",
                    "return_reason_id": null,
                    "orders_status_id": 5,
                    "current_route_id": 3964,
                    "allow_dropoff": 1,
                    "pin_required": 1,
                    "created_at": "2024-01-15 10:30:00",
                    "driverNotes": [],
                    "files": {
                      "photo_urls": [],
                      "signature_urls": []
                    },
                    "is_finished": 0,
                    "is_postponed": 0,
                    "full_address": "DEMO,Montreal,QC,H4E3R3",
                    "operation_mode": 0,
                    "is_multiple": 1,
                    "total_orders": 2,
                    "current_order": 2,
                    "is_recurring_pickup": false,
                    "can_hand_off": false
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Recurring pickups (additive, after every existing key): is_recurring_pickup marks a mandatory recurring pickup stop; can_hand_off is false for such a stop and otherwise follows the route's allow_hands_off_order_by_driver (the hand-off endpoints refuse a recurring stop with recurring_pickups.skip_instead either way). Recipient privacy (client setting, off by default): once the driver has ended the route, or the client's chosen number of days after the route date has passed, name, company_name, email and telephone are empty strings; every key and the address stay. Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route.",
        "x-route-name": "openapp.driver.routes.routeId.orders.get",
        "x-capability": "driver.routes",
        "x-graphql": "driverRoutesOrders",
        "operationId": "driverRoutesOrders"
      }
    },
    "/app/v1/driver/firebase/routes/{routeId}/area/{area}": {
      "get": {
        "summary": "GET /app/v1/driver/firebase/routes/{routeId}/area/{area}",
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.firebase.routes.routeId.area.area.get",
        "x-capability": "driver.routes",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route.",
        "operationId": "driverFirebaseRoutesRouteIdAreaAreaGet"
      }
    },
    "/app/v1/driver/routes/{routeId}/orders/{orderId}/remove": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Remove order from route by orderId",
        "parameters": [
          {
            "in": "path",
            "name": "routeId",
            "schema": {
              "type": "integer"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "orderId",
            "schema": {
              "type": "integer"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "route_id": {
                      "type": "integer"
                    },
                    "deleted_order_id": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Successful",
                  "route_id": 123,
                  "deleted_order_id": 102223
                }
              }
            }
          },
          "400": {
            "description": "Bad Request. A delivered or failed stop answers error_code `hand_off_finished_stop`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "A delivered or failed stop cannot be handed off"
                    },
                    "error_code": {
                      "type": "string",
                      "example": "hand_off_finished_stop",
                      "description": "Present only when the stop is already delivered or failed."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Remove order from route by orderId. A stop the driver already delivered or failed cannot be handed off: the request answers 400 with error_code `hand_off_finished_stop` and nothing is changed. Every hand-off is recorded in the order's operation history as `driver handed off order`, with the stop number it left. Driver apps only; needs driver.route_edit on the token. Answered exactly as the internal driver route.",
        "x-route-name": "openapp.driver.routes.routeId.orders.orderId.remove.post",
        "x-capability": "driver.route_edit",
        "x-graphql": "driverRoutesOrdersRemove",
        "operationId": "driverRoutesOrdersRemove"
      }
    },
    "/app/v1/driver/routes/{routeId}/orders/batchremove": {
      "post": {
        "summary": "Batch remove orders from a route",
        "description": "Allows a driver to batch remove their own orders from a specific route if allowed. A stop the driver already delivered or failed cannot be handed off: the request answers 400 with error_code `hand_off_finished_stop` and `refused_order_ids`; no order of the batch is handed off and nothing is changed. Every hand-off is recorded in the order's operation history as `driver handed off order`, with the stop number it left. Driver apps only; needs driver.route_edit on the token. Answered exactly as the internal driver route.",
        "tags": [
          "Driver"
        ],
        "parameters": [
          {
            "name": "routeId",
            "in": "path",
            "description": "The ID of the route.",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 1234
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "order_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "example": 5678
                    },
                    "description": "List of order IDs to remove from the route."
                  }
                },
                "required": [
                  "order_ids"
                ]
              },
              "example": {
                "order_ids": [
                  5678,
                  5679,
                  5680
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Orders successfully removed from the route.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Successful"
                    },
                    "route_id": {
                      "type": "integer",
                      "example": 1234
                    },
                    "deleted_order_ids": {
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "example": 5678
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request. Possible reasons: missing fields, route not found, not allowed to remove, no valid orders, or server error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Missing Mandatory field order_ids"
                    },
                    "error_code": {
                      "type": "string",
                      "example": "hand_off_finished_stop",
                      "description": "Present only when a stop of the batch is already delivered or failed."
                    },
                    "refused_order_ids": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "example": [
                        1880353
                      ],
                      "description": "The delivered or failed stops; present with error_code `hand_off_finished_stop`."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.routes.routeId.orders.batchremove.post",
        "x-capability": "driver.route_edit",
        "x-graphql": "driverRoutesOrdersBatchremove",
        "operationId": "driverRoutesOrdersBatchremove"
      }
    },
    "/app/v1/driver/routes/{routeId}/get-stop-number/{ref}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get order stop number by ref/orderid/trackingnumber",
        "parameters": [
          {
            "in": "path",
            "name": "routeId",
            "schema": {
              "type": "integer"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "ref",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "integer"
                    },
                    "stopnumber": {
                      "type": "string"
                    },
                    "stop_number": {
                      "type": "integer",
                      "description": "The bare stop number. Read this instead of splitting `stopnumber`: a driver alias may itself contain \"-\"."
                    },
                    "order/tracking/operationevents_id": {
                      "type": "integer"
                    },
                    "packages": {
                      "type": "integer"
                    },
                    "ref": {
                      "type": "string"
                    },
                    "tracking_number": {
                      "type": "string"
                    },
                    "store_grid": {
                      "type": "string"
                    },
                    "orders_scanned": {
                      "type": "integer"
                    },
                    "orders_unscanned": {
                      "type": "integer"
                    },
                    "orders_total": {
                      "type": "integer"
                    },
                    "route_id": {
                      "type": "integer",
                      "description": "The route the scan resolved to. For a per-route scan this is the route asked about; when an order was planned on more than one route, labels printed from this answer name this route."
                    }
                  }
                },
                "example": {
                  "result": 1,
                  "stopnumber": "driver001-1",
                  "stop_number": 1,
                  "order/tracking/operationevents_id": 18458,
                  "packages": 1,
                  "ref": "test-03",
                  "tracking_number": "SR585479158593",
                  "store_grid": "",
                  "orders_scanned": 1,
                  "orders_unscanned": 49,
                  "orders_total": 50,
                  "route_id": 1024
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Get order stop number by ref/orderid/trackingnumber. An order on hold is not loaded: the scan answers result 0 with code `order_on_hold` and a message for the driver, and the scan is not counted. An intercepted order (status 48) is refused the same way with code `order_intercepted`. Driver apps only; needs driver.scan on the token. Answered exactly as the internal driver route.",
        "x-route-name": "openapp.driver.routes.routeId.get-stop-number.ref.get",
        "x-capability": "driver.scan",
        "x-graphql": "driverRoutesGetStopNumber",
        "operationId": "driverRoutesGetStopNumber"
      }
    },
    "/app/v1/driver/routes/{routeId}/add-order/{ref}": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Add order to route by ref/orderid/trackingnumber",
        "parameters": [
          {
            "in": "path",
            "name": "routeId",
            "schema": {
              "type": "integer"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "ref",
            "schema": {
              "type": "string"
            },
            "required": true
          },
          {
            "in": "query",
            "name": "optimize",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "required": false
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "order_id": {
                      "type": "integer"
                    },
                    "ref": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message": "Order added to route successfully",
                  "order_id": 18458,
                  "ref": "test-03",
                  "name": "test-03"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "409": {
            "description": "An order is on hold or cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "order_on_hold",
                        "order_cancelled"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Add order to route by ref/orderid/trackingnumber. An order the same driver handed off this route goes back to the stop number it left, when that stop is still free; any other order is added after the driver's last stop. An order on hold or cancelled is refused with 409, code `order_on_hold` or `order_cancelled`; nothing is added. Driver apps only; needs driver.route_edit on the token. Answered exactly as the internal driver route.",
        "x-route-name": "openapp.driver.routes.routeId.add-order.ref.post",
        "x-capability": "driver.route_edit",
        "x-graphql": "driverRoutesAddOrder",
        "operationId": "driverRoutesAddOrder"
      }
    },
    "/app/v1/driver/routes/{routeId}/batch-add-orders-by-driver": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Batch Add Orders to Route by Driver",
        "description": "Allows an authenticated driver to batch assign orders to a specific route using the routeId in the path. An order the same driver handed off this route goes back to the stop number it left, when that stop is still free; any other order is added after the driver's last stop. An order on hold or cancelled is refused with 409, code `order_on_hold` or `order_cancelled` and `refused_order_ids`; nothing is added. Driver apps only; needs driver.route_edit on the token. Answered exactly as the internal driver route.",
        "operationId": "batchAddOrdersToRouteByDriver",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "routeId",
            "in": "path",
            "description": "ID of the route to which orders will be assigned",
            "required": true,
            "schema": {
              "type": "integer",
              "example": 456
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "order_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "example": [
                      101,
                      102,
                      103
                    ]
                  }
                },
                "required": [
                  "order_ids"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Orders successfully added to the route",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Orders successfully added to route"
                    },
                    "order_ids": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "example": [
                        101,
                        102,
                        103
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid route ID or orders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Route not found"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "409": {
            "description": "Some orders are already assigned to another route. Also returned for an order on hold or cancelled, with `code` order_on_hold / order_cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Some orders are already assigned to another route"
                    },
                    "conflict_order_ids": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "example": [
                        104,
                        105
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation failed for order_ids",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "object",
                      "example": {
                        "order_ids": [
                          "The order_ids field is required."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Failed to add orders to route"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.routes.routeId.batch-add-orders-by-driver.post",
        "x-capability": "driver.route_edit",
        "x-graphql": "driverRoutesBatchAddOrdersByDriver"
      }
    },
    "/app/v1/driver/routes/{routeId}/points": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get points on route for  one driver",
        "parameters": [
          {
            "in": "path",
            "name": "routeId",
            "schema": {
              "type": "integer"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "startPoint": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "unique_identifier": {
                            "type": "string"
                          },
                          "business_id": {
                            "type": "integer"
                          },
                          "description": {
                            "type": "string"
                          },
                          "postcode": {
                            "type": "string"
                          },
                          "street_number": {
                            "type": "string"
                          },
                          "street_name": {
                            "type": "string"
                          },
                          "apt": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "province": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          },
                          "lat": {
                            "type": "string"
                          },
                          "lng": {
                            "type": "string"
                          },
                          "telephone": {
                            "type": "string"
                          },
                          "territory": {
                            "type": "integer"
                          },
                          "is_point": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "integer"
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "updated_at": {
                            "type": "string"
                          },
                          "territory_info": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "center": {
                                "type": "string"
                              },
                              "coordinate_array": {
                                "type": "string"
                              },
                              "business_id": {
                                "type": "integer"
                              },
                              "status": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      },
                      "endPoint": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "unique_identifier": {
                            "type": "string"
                          },
                          "business_id": {
                            "type": "integer"
                          },
                          "description": {
                            "type": "string"
                          },
                          "postcode": {
                            "type": "string"
                          },
                          "street_number": {
                            "type": "string"
                          },
                          "street_name": {
                            "type": "string"
                          },
                          "apt": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "province": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          },
                          "lat": {
                            "type": "string"
                          },
                          "lng": {
                            "type": "string"
                          },
                          "telephone": {
                            "type": "string"
                          },
                          "territory": {
                            "type": "integer"
                          },
                          "is_point": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "integer"
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "updated_at": {
                            "type": "string"
                          },
                          "territory_info": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "center": {
                                "type": "string"
                              },
                              "coordinate_array": {
                                "type": "string"
                              },
                              "business_id": {
                                "type": "integer"
                              },
                              "status": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      },
                      "breaks": {
                        "type": "array",
                        "description": "Additive. The driver breaks planned on this driver's run, earliest first; an empty array when the run has none. Every other field is unchanged.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "start": {
                              "type": "string",
                              "example": "2026-09-14 12:10:00",
                              "description": "When the break starts (Y-m-d H:i:s, the route's local time)."
                            },
                            "end": {
                              "type": "string",
                              "example": "2026-09-14 12:40:00",
                              "description": "When the break ends (Y-m-d H:i:s, the route's local time)."
                            },
                            "minutes": {
                              "type": "integer",
                              "example": 30,
                              "description": "Break length in minutes."
                            },
                            "after_stop_number": {
                              "type": "integer",
                              "nullable": true,
                              "example": 7,
                              "description": "Stop number the break follows; null means before the first stop."
                            },
                            "addressbook_id": {
                              "type": "integer",
                              "nullable": true,
                              "example": 31,
                              "description": "Additive, sRoute 2T 1.0.21: present only for a break taken at one of its places, the address book entry of that place (null when not known)."
                            },
                            "name": {
                              "type": "string",
                              "nullable": true,
                              "example": "Coffee stop",
                              "description": "Additive, sRoute 2T 1.0.21: present only for a break at a place, the place's address book name."
                            },
                            "latitude": {
                              "type": "number",
                              "nullable": true,
                              "example": 45.5088,
                              "description": "Additive, sRoute 2T 1.0.21: present only for a break at a place."
                            },
                            "longitude": {
                              "type": "number",
                              "nullable": true,
                              "example": -73.5878,
                              "description": "Additive, sRoute 2T 1.0.21: present only for a break at a place."
                            }
                          }
                        }
                      },
                      "reload_stops": {
                        "type": "array",
                        "description": "Additive (phase P3). The reloads at a depot planned between the trips of this driver's run, earliest first: sequential trips on sRoute and sRoute 2 (phase P3) or the reload stops sRoute 2T 1.0.20 plans itself, in the same shape; an empty array when the run has none. Every other field is unchanged.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "start": {
                              "type": "string",
                              "example": "2026-09-14 13:05:00",
                              "description": "When the vehicle is at the depot (Y-m-d H:i:s, the route's local time)."
                            },
                            "end": {
                              "type": "string",
                              "example": "2026-09-14 13:25:00",
                              "description": "When loading is done."
                            },
                            "minutes": {
                              "type": "integer",
                              "example": 20,
                              "description": "Loading time in minutes."
                            },
                            "after_stop_number": {
                              "type": "integer",
                              "nullable": true,
                              "example": 12,
                              "description": "Stop number the reload follows; null = before the first stop."
                            },
                            "trip": {
                              "type": "integer",
                              "nullable": true,
                              "example": 1,
                              "description": "The trip the reload ends (1 = after the first trip)."
                            },
                            "addressbook_id": {
                              "type": "integer",
                              "nullable": true,
                              "example": 12,
                              "description": "The depot's address book id."
                            },
                            "name": {
                              "type": "string",
                              "nullable": true,
                              "example": "Main warehouse",
                              "description": "The depot's name."
                            },
                            "latitude": {
                              "type": "number",
                              "nullable": true,
                              "example": 45.5017
                            },
                            "longitude": {
                              "type": "number",
                              "nullable": true,
                              "example": -73.5673
                            }
                          }
                        }
                      },
                      "delivery_alternatives": {
                        "type": "array",
                        "description": "Additive. The stops of this driver's run delivered at one of the order's alternative delivery locations instead of the order's own address (the order's address is unchanged), in stop order; an empty array when there are none. Every other field is unchanged.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "order_id": {
                              "type": "integer",
                              "example": 1234
                            },
                            "stop_number": {
                              "type": "integer",
                              "nullable": true,
                              "example": 4
                            },
                            "alternative_id": {
                              "type": "integer",
                              "example": 88,
                              "description": "The order's delivery alternative the stop is served at."
                            },
                            "addressbook_id": {
                              "type": "integer",
                              "nullable": true,
                              "example": null
                            },
                            "name": {
                              "type": "string",
                              "nullable": true,
                              "example": null,
                              "description": "The address book name, for an alternative that is an address book entry."
                            },
                            "address": {
                              "type": "string",
                              "example": "100 Rue Sainte-Catherine, Montreal"
                            },
                            "latitude": {
                              "type": "number",
                              "nullable": true,
                              "example": 45.5075
                            },
                            "longitude": {
                              "type": "number",
                              "nullable": true,
                              "example": -73.5605
                            },
                            "time_window_start": {
                              "type": "string",
                              "nullable": true,
                              "example": "2026-09-14 13:00:00"
                            },
                            "time_window_end": {
                              "type": "string",
                              "nullable": true,
                              "example": "2026-09-14 15:00:00"
                            }
                          }
                        }
                      },
                      "recurring_pickup_route": {
                        "type": "boolean",
                        "description": "Generated from a recurring pickup template"
                      },
                      "allow_adhoc_pickups": {
                        "type": "boolean",
                        "description": "Non-recurring pickup orders may join the route (true for every non-recurring route)"
                      },
                      "allow_deliveries": {
                        "type": "boolean",
                        "description": "Delivery orders may join the route (true for every non-recurring route)"
                      },
                      "shifts": {
                        "type": "array",
                        "description": "Additive, after every existing key. The shifts the driver's run is split into (up to six), in order; an empty array when the run is one shift. Every other field is unchanged.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "shift": {
                              "type": "integer",
                              "example": 1,
                              "description": "1 = the first shift."
                            },
                            "start": {
                              "type": "string",
                              "example": "08:00",
                              "description": "Shift start (HH:MM, the route's local time)."
                            },
                            "end": {
                              "type": "string",
                              "example": "12:00",
                              "description": "Shift end (HH:MM)."
                            },
                            "start_address": {
                              "type": "object",
                              "nullable": true,
                              "description": "Where the shift starts (start_address) or ends (end_address); null = the run's own start or end address.",
                              "properties": {
                                "addressbook_id": {
                                  "type": "integer",
                                  "example": 12
                                },
                                "name": {
                                  "type": "string",
                                  "nullable": true,
                                  "example": "Main warehouse"
                                },
                                "latitude": {
                                  "type": "number",
                                  "nullable": true,
                                  "example": 45.5017
                                },
                                "longitude": {
                                  "type": "number",
                                  "nullable": true,
                                  "example": -73.5673
                                }
                              }
                            },
                            "end_address": {
                              "type": "object",
                              "nullable": true,
                              "description": "Where the shift starts (start_address) or ends (end_address); null = the run's own start or end address.",
                              "properties": {
                                "addressbook_id": {
                                  "type": "integer",
                                  "example": 12
                                },
                                "name": {
                                  "type": "string",
                                  "nullable": true,
                                  "example": "Main warehouse"
                                },
                                "latitude": {
                                  "type": "number",
                                  "nullable": true,
                                  "example": 45.5017
                                },
                                "longitude": {
                                  "type": "number",
                                  "nullable": true,
                                  "example": -73.5673
                                }
                              }
                            },
                            "planned_start": {
                              "type": "string",
                              "nullable": true,
                              "example": "2026-09-14 13:00:00",
                              "description": "When the planned run starts this shift (Y-m-d H:i:s); null for the first shift and before planning."
                            },
                            "planned_end": {
                              "type": "string",
                              "nullable": true,
                              "example": "2026-09-14 11:50:00",
                              "description": "When the planned run comes back at the end of this shift (Y-m-d H:i:s); null before planning."
                            },
                            "starts_after_stop_number": {
                              "type": "integer",
                              "nullable": true,
                              "example": 7,
                              "description": "Stop number the shift starts after; null = before the first stop."
                            },
                            "ends_after_stop_number": {
                              "type": "integer",
                              "nullable": true,
                              "example": 7,
                              "description": "Stop number the shift ends after."
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": [
                  {
                    "startPoint": {
                      "id": 2,
                      "name": "Home",
                      "unique_identifier": "home",
                      "business_id": 2,
                      "description": "",
                      "postcode": "H9S2H9",
                      "street_number": "40",
                      "street_name": "BOUL Des Sources",
                      "apt": "D",
                      "city": "Pointe-claire",
                      "province": "Quebec",
                      "country": "Canada",
                      "lat": "45.4484317",
                      "lng": "-73.7799527",
                      "telephone": "5144444444",
                      "territory": 1,
                      "is_point": 1,
                      "status": 1,
                      "created_at": "2020-05-10 17:21:43.00",
                      "updated_at": "2020-05-10 17:21:43.00",
                      "territory_info": {
                        "id": 1,
                        "name": "Great Montreal Area",
                        "center": "[24.886,-70.268]",
                        "coordinate_array": "",
                        "business_id": 0,
                        "status": 1
                      }
                    },
                    "endPoint": {
                      "id": 2,
                      "name": "Home",
                      "unique_identifier": "home",
                      "business_id": 2,
                      "description": "",
                      "postcode": "H9S2H9",
                      "street_number": "40",
                      "street_name": "BOUL Des Sources",
                      "apt": "D",
                      "city": "Pointe-claire",
                      "province": "Quebec",
                      "country": "Canada",
                      "lat": "45.4484317",
                      "lng": "-73.7799527",
                      "telephone": "5144444444",
                      "territory": 1,
                      "is_point": 1,
                      "status": 1,
                      "created_at": "2020-05-10 17:21:43.00",
                      "updated_at": "2020-05-10 17:21:43.00",
                      "territory_info": {
                        "id": 1,
                        "name": "Great Montreal Area",
                        "center": "[24.886,-70.268]",
                        "coordinate_array": "",
                        "business_id": 0,
                        "status": 1
                      }
                    },
                    "breaks": [
                      {
                        "start": "2026-09-14 12:10:00",
                        "end": "2026-09-14 12:40:00",
                        "minutes": 30,
                        "after_stop_number": 7
                      }
                    ],
                    "reload_stops": [
                      {
                        "start": "2026-09-14 13:05:00",
                        "end": "2026-09-14 13:25:00",
                        "minutes": 20,
                        "after_stop_number": 12,
                        "trip": 1,
                        "addressbook_id": 12,
                        "name": "Main warehouse",
                        "latitude": 45.5017,
                        "longitude": -73.5673
                      }
                    ],
                    "delivery_alternatives": [
                      {
                        "order_id": 1234,
                        "stop_number": 4,
                        "alternative_id": 88,
                        "addressbook_id": null,
                        "name": null,
                        "address": "100 Rue Sainte-Catherine, Montreal",
                        "latitude": 45.5075,
                        "longitude": -73.5605,
                        "time_window_start": "2026-09-14 13:00:00",
                        "time_window_end": "2026-09-14 15:00:00"
                      }
                    ],
                    "recurring_pickup_route": false,
                    "allow_adhoc_pickups": true,
                    "allow_deliveries": true,
                    "shifts": [
                      {
                        "shift": 1,
                        "start": "08:00",
                        "end": "12:00",
                        "start_address": null,
                        "end_address": {
                          "addressbook_id": 12,
                          "name": "Main warehouse",
                          "latitude": 45.5017,
                          "longitude": -73.5673
                        },
                        "planned_start": null,
                        "planned_end": "2026-09-14 11:50:00",
                        "starts_after_stop_number": null,
                        "ends_after_stop_number": 7
                      },
                      {
                        "shift": 2,
                        "start": "13:00",
                        "end": "17:00",
                        "start_address": {
                          "addressbook_id": 12,
                          "name": "Main warehouse",
                          "latitude": 45.5017,
                          "longitude": -73.5673
                        },
                        "end_address": null,
                        "planned_start": "2026-09-14 13:00:00",
                        "planned_end": null,
                        "starts_after_stop_number": 7,
                        "ends_after_stop_number": null
                      }
                    ]
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Start and end point, scan counts and geometry of the acting driver's run on the route. `breaks` (additive) lists the driver breaks planned on the run: start, end, minutes and after_stop_number (null = before the first stop); it is an empty array when the run has no breaks. `reload_stops` (additive, phase P3) lists the reloads at a depot planned between the trips of the run: start, end, minutes, after_stop_number, trip, and the depot (addressbook_id, name, latitude, longitude); it is an empty array when the run has none. A break taken at one of its places (sRoute 2T 1.0.21) also carries addressbook_id, name, latitude and longitude. `delivery_alternatives` (additive) lists the stops delivered at one of the order's alternative delivery locations: order_id, stop_number, alternative_id, addressbook_id, name, address, latitude, longitude, time_window_start and time_window_end; it is an empty array when there are none. Recurring pickups (additive, after every existing key): recurring_pickup_route tells a route generated from a recurring pickup template; allow_adhoc_pickups and allow_deliveries are its two switches (true for every other route, and before the recurring pickup migrations). `shifts` (additive, after every existing key) lists the shifts the run is split into, each with shift, start and end (HH:MM), start_address and end_address (null = the run's own start or end address), planned_start, planned_end, starts_after_stop_number and ends_after_stop_number; an empty array when the run is one shift. Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route.",
        "x-route-name": "openapp.driver.routes.routeId.points.get",
        "x-capability": "driver.routes",
        "x-graphql": "driverRoutesPoints",
        "operationId": "driverRoutesPoints"
      }
    },
    "/app/v1/driver/orders-status": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get order status list",
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "S": {
                      "type": "string"
                    },
                    "NR": {
                      "type": "string"
                    },
                    "RL": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "S": "Successful",
                  "NR": "Need Rescheduled",
                  "RL": "Reschedule Later"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders-status.get",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrdersStatus",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverOrdersStatus"
      },
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Update order status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderStatusUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orderId": {
                      "type": "integer"
                    },
                    "operation_event_id": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "orderId": 12708,
                  "operation_event_id": 211,
                  "message": "Success"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "422": {
            "description": "Delivery PIN verification failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid delivery PIN"
                    }
                  }
                },
                "examples": {
                  "PIN required": {
                    "value": {
                      "result": false,
                      "message": "Delivery PIN is required"
                    }
                  },
                  "Invalid PIN": {
                    "value": {
                      "result": false,
                      "message": "Invalid delivery PIN"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The order is on hold or cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Order WP2610020010095 is on hold. Do not deliver it; bring it back to the warehouse."
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "order_on_hold",
                        "order_cancelled"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Update order status. An order on hold or cancelled cannot be completed by the driver: the request answers 409 with code `order_on_hold` or `order_cancelled` and a message to show to the driver; nothing changes. An intercepted order (status 48) is refused the same way with code `order_intercepted`. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "x-route-name": "openapp.driver.orders-status.post",
        "x-capability": "driver.delivery",
        "operationId": "driverOrdersStatusPost"
      }
    },
    "/app/v1/driver/routes/validate-order": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Validate if ref matches order_id",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateRefOrderId"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "ref matches order"
          },
          "400": {
            "description": "Bad Request"
          },
          "404": {
            "description": "Not found"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.routes.validate-order.post",
        "x-capability": "driver.scan",
        "x-graphql": "driverRoutesValidateOrder",
        "description": "Driver apps only; needs driver.scan on the token. Answered exactly as the internal driver route.",
        "operationId": "driverRoutesValidateOrder"
      }
    },
    "/app/v1/driver/addGpsTackingRecord": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Add Gps Tracking Record",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "latitude": {
                    "type": "string",
                    "description": "Required. GPS latitude coordinate."
                  },
                  "longitude": {
                    "type": "string",
                    "description": "Required. GPS longitude coordinate."
                  },
                  "route_id": {
                    "type": "string",
                    "nullable": true,
                    "description": "Optional. Route ID associated with this GPS record."
                  },
                  "order_id": {
                    "type": "string",
                    "nullable": true,
                    "description": "Optional. Order ID associated with this GPS record."
                  }
                },
                "required": [
                  "latitude",
                  "longitude"
                ]
              },
              "examples": {
                "example": {
                  "value": {
                    "latitude": "45.5261811",
                    "longitude": "-73.6496515",
                    "route_id": null,
                    "order_id": null
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message": "Success"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.addGpsTackingRecord.post",
        "x-capability": "driver.location",
        "x-graphql": "driverAddGpsTackingRecord",
        "description": "Driver apps only; needs driver.location on the token. Answered exactly as the internal driver route.",
        "operationId": "driverAddGpsTackingRecord"
      }
    },
    "/app/v1/driver/orders/{orderId}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get order by Id",
        "description": "Recipient privacy (client setting, off by default): once the driver has ended the order's route, or the client's chosen number of days after the route date has passed, name, email and telephone are empty strings, as are the contact keys of shipping_order.pickup_address / delivery_address; every key and the address stay. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "orderId",
            "schema": {
              "type": "integer"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "ref": {
                      "type": "string"
                    },
                    "address_1": {
                      "type": "string"
                    },
                    "address_2": {
                      "type": "string"
                    },
                    "city": {
                      "type": "string"
                    },
                    "province": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string"
                    },
                    "postcode": {
                      "type": "string"
                    },
                    "buzz_code": {
                      "type": "string"
                    },
                    "latitude": {
                      "type": "string"
                    },
                    "longitude": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string"
                    },
                    "telephone": {
                      "type": "string"
                    },
                    "tracking_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "note": {
                      "type": "string"
                    },
                    "driver_alias": {
                      "type": "string"
                    },
                    "stop_number": {
                      "type": "integer"
                    },
                    "status": {
                      "type": "string"
                    },
                    "packages": {
                      "type": "integer"
                    },
                    "notification_language": {
                      "type": "string"
                    },
                    "return_reason_id": {
                      "type": "integer"
                    },
                    "files": {
                      "type": "object",
                      "properties": {
                        "signature_urls": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "url": {
                                "type": "string"
                              },
                              "operation_event_id": {
                                "type": "string",
                                "nullable": true
                              },
                              "gps_tracking_id": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "photo_urls": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "url": {
                                "type": "string"
                              },
                              "operation_event_id": {
                                "type": "string",
                                "nullable": true
                              },
                              "gps_tracking_id": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        }
                      }
                    },
                    "driverNotes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "full_address": {
                      "type": "string"
                    },
                    "allow_dropoff": {
                      "type": "integer"
                    },
                    "related_order_type": {
                      "type": "integer",
                      "nullable": true
                    },
                    "related_order_id": {
                      "type": "integer",
                      "nullable": true
                    },
                    "could_edit_items": {
                      "type": "boolean",
                      "description": "Whether the driver can edit related order items. True when related_order_type is storage_order (3), moving_order (5), or shipping_order (9)."
                    },
                    "related_order_items": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "related_order_type": {
                          "type": "integer"
                        },
                        "related_order_id": {
                          "type": "integer"
                        },
                        "related_order_name": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "grouped_items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "packaging_id": {
                                "type": "integer",
                                "nullable": true
                              },
                              "packaging_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "description": {
                                "type": "string",
                                "nullable": true
                              },
                              "length": {
                                "type": "number",
                                "nullable": true
                              },
                              "width": {
                                "type": "number",
                                "nullable": true
                              },
                              "height": {
                                "type": "number",
                                "nullable": true
                              },
                              "dimension_unit": {
                                "type": "integer",
                                "nullable": true
                              },
                              "weight": {
                                "type": "number",
                                "nullable": true
                              },
                              "weight_unit": {
                                "type": "integer",
                                "nullable": true
                              },
                              "value": {
                                "type": "number",
                                "nullable": true
                              },
                              "qty": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        "raw_items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "packaging_id": {
                                "type": "integer",
                                "nullable": true
                              },
                              "packaging_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "description": {
                                "type": "string",
                                "nullable": true
                              },
                              "length": {
                                "type": "number",
                                "nullable": true
                              },
                              "width": {
                                "type": "number",
                                "nullable": true
                              },
                              "height": {
                                "type": "number",
                                "nullable": true
                              },
                              "dimension_unit": {
                                "type": "integer",
                                "nullable": true
                              },
                              "weight": {
                                "type": "number",
                                "nullable": true
                              },
                              "weight_unit": {
                                "type": "integer",
                                "nullable": true
                              },
                              "value": {
                                "type": "number",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "products": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "product_id": {
                                "type": "integer"
                              },
                              "product_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "quantity": {
                                "type": "integer"
                              },
                              "unit_price": {
                                "type": "number"
                              },
                              "total_price": {
                                "type": "number"
                              }
                            }
                          }
                        },
                        "summary": {
                          "type": "object",
                          "properties": {
                            "total_item_count": {
                              "type": "integer"
                            },
                            "total_group_count": {
                              "type": "integer"
                            },
                            "total_grouped_quantity": {
                              "type": "integer"
                            },
                            "total_product_quantity": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    },
                    "created_at": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "id": 10410,
                  "ref": "84040085",
                  "address_1": "2300 ainsley crescent",
                  "address_2": "",
                  "city": "Mont-royal",
                  "province": "QC",
                  "country": "Canada",
                  "postcode": "H3P2S7",
                  "buzz_code": "",
                  "latitude": "45.5261811",
                  "longitude": "-73.6496515",
                  "name": "Customer 172",
                  "email": "172@sr.com",
                  "telephone": "5144309193",
                  "tracking_number": null,
                  "note": "Note 172",
                  "driver_alias": "driver001",
                  "stop_number": 1,
                  "status": "Successful",
                  "packages": 1,
                  "notification_language": "",
                  "return_reason_id": 1,
                  "files": {
                    "signature_urls": [
                      {
                        "id": 1555,
                        "url": "https://admin.superroute.ca/storage/2020-08-17/10410_S_In1mB3gI2ntwsKg.jpeg",
                        "operation_event_id": null,
                        "gps_tracking_id": null
                      }
                    ],
                    "photo_urls": [
                      {
                        "id": 1528,
                        "url": "https://admin.superroute.ca/storage/2020-08-16/10410_P_pNQhAWt8d1Ow3NQ.jpeg",
                        "operation_event_id": null,
                        "gps_tracking_id": null
                      }
                    ]
                  },
                  "driverNotes": [],
                  "full_address": "22 boul des sources, pointe claire, h9s2h9",
                  "allow_dropoff": 1,
                  "related_order_type": 3,
                  "related_order_id": 1231,
                  "could_edit_itmes": true,
                  "related_order_items": {
                    "related_order_type": 3,
                    "related_order_id": 1231,
                    "related_order_name": "storage_order",
                    "status": "confirmed",
                    "grouped_items": [
                      {
                        "packaging_id": null,
                        "packaging_name": null,
                        "description": "Desk xxx",
                        "length": 120,
                        "width": 60,
                        "height": 75,
                        "dimension_unit": 1,
                        "weight": null,
                        "weight_unit": null,
                        "value": null,
                        "qty": 2
                      }
                    ],
                    "raw_items": [
                      {
                        "packaging_id": null,
                        "packaging_name": null,
                        "description": "Desk xxx",
                        "length": 120,
                        "width": 60,
                        "height": 75,
                        "dimension_unit": 1,
                        "weight": null,
                        "weight_unit": null,
                        "value": null
                      }
                    ],
                    "products": [],
                    "summary": {
                      "total_item_count": 2,
                      "total_group_count": 1,
                      "total_grouped_quantity": 2,
                      "total_product_quantity": 0
                    }
                  },
                  "pin_required": 1,
                  "created_at": "2024-01-15 10:30:00"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.get",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrders",
        "operationId": "driverOrders"
      }
    },
    "/app/v1/driver/orders/{orderId}/price-detail": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get unified price detail for an order",
        "description": "Returns the latest price breakdown for the order. If the order is linked to a storage, moving, or shipping order, returns the related order's price details in a unified format. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "orderId",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "example": 10001
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "order_id": {
                      "type": "integer",
                      "example": 10001
                    },
                    "price_type": {
                      "type": "string",
                      "enum": [
                        "delivery",
                        "storage_order",
                        "moving_order",
                        "shipping_order",
                        "label_service"
                      ],
                      "example": "storage_order"
                    },
                    "currency": {
                      "type": "string",
                      "example": "CAD"
                    },
                    "price_details": {
                      "type": "array",
                      "description": "Breakdown of individual fee components",
                      "items": {
                        "type": "object",
                        "properties": {
                          "label": {
                            "type": "string",
                            "example": "Storage"
                          },
                          "amount": {
                            "type": "number",
                            "example": 50
                          }
                        }
                      }
                    },
                    "surcharge_items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "example": "Stairs"
                          },
                          "amount": {
                            "type": "number",
                            "example": 10
                          },
                          "quantity": {
                            "type": "integer",
                            "example": 2
                          },
                          "calculated_amount": {
                            "type": "number",
                            "example": 20
                          }
                        }
                      }
                    },
                    "promotion_discount": {
                      "type": "number",
                      "example": 5
                    },
                    "total_price": {
                      "type": "number",
                      "example": 120.5
                    },
                    "paid_amount": {
                      "type": "number",
                      "nullable": true,
                      "example": 80
                    },
                    "tax": {
                      "type": "object",
                      "properties": {
                        "total_tax": {
                          "type": "number",
                          "example": 6.5
                        },
                        "tax_details": {
                          "type": "array",
                          "description": "Breakdown of individual tax components",
                          "items": {
                            "type": "object",
                            "properties": {
                              "tax_name": {
                                "type": "string",
                                "example": "GST"
                              },
                              "tax_rate": {
                                "type": "number",
                                "example": 5
                              },
                              "tax_amount": {
                                "type": "number",
                                "example": 3.25
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Order not found"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.price-detail.get",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrderPriceDetail",
        "operationId": "driverOrderPriceDetail"
      }
    },
    "/app/v1/driver/orders/{orderId}/related-order-items": {
      "patch": {
        "tags": [
          "Driver"
        ],
        "summary": "Update related storage/moving/shipping order items by driver order id",
        "parameters": [
          {
            "in": "path",
            "name": "orderId",
            "schema": {
              "type": "integer"
            },
            "required": true
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "qty": {
                          "type": "integer",
                          "description": "Target quantity for this grouped item. Use 0 to delete the group."
                        },
                        "packaging_id": {
                          "type": "integer",
                          "nullable": true
                        },
                        "description": {
                          "type": "string",
                          "nullable": true
                        },
                        "length": {
                          "type": "number",
                          "nullable": true
                        },
                        "width": {
                          "type": "number",
                          "nullable": true
                        },
                        "height": {
                          "type": "number",
                          "nullable": true
                        },
                        "dimension_unit": {
                          "type": "integer",
                          "nullable": true
                        },
                        "weight": {
                          "type": "number",
                          "nullable": true
                        },
                        "weight_unit": {
                          "type": "integer",
                          "nullable": true
                        },
                        "value": {
                          "type": "number",
                          "nullable": true
                        }
                      },
                      "required": [
                        "qty"
                      ]
                    }
                  }
                },
                "required": [
                  "items"
                ]
              },
              "example": {
                "items": [
                  {
                    "qty": 1,
                    "description": "Desk xxx",
                    "length": 120,
                    "width": 60,
                    "height": 75,
                    "dimension_unit": 1,
                    "weight": 35,
                    "weight_unit": 2
                  },
                  {
                    "qty": 2,
                    "description": "Desk xxx",
                    "length": 120,
                    "width": 60,
                    "height": 75,
                    "dimension_unit": 1,
                    "weight": 35,
                    "weight_unit": 2
                  },
                  {
                    "description": "Old cabinet",
                    "length": 80,
                    "width": 40,
                    "height": 180,
                    "dimension_unit": 1,
                    "weight": 45,
                    "weight_unit": 2,
                    "qty": 0
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "order_id": {
                      "type": "integer"
                    },
                    "related_order_type": {
                      "type": "integer"
                    },
                    "related_order_id": {
                      "type": "integer"
                    },
                    "related_order_items": {
                      "type": "object",
                      "nullable": true
                    },
                    "price_recalculated": {
                      "type": "boolean",
                      "description": "Whether the related order price was recalculated after the update"
                    },
                    "estimate_price_response": {
                      "type": "object",
                      "nullable": true,
                      "description": "The new price breakdown after recalculation (null if price was not recalculated)"
                    }
                  }
                },
                "example": {
                  "message": "Success",
                  "order_id": 10410,
                  "related_order_type": 9,
                  "related_order_id": 501,
                  "could_edit_itmes": true,
                  "related_order_items": {
                    "related_order_type": 9,
                    "related_order_id": 501,
                    "related_order_name": "shipping_order",
                    "status": 1,
                    "grouped_items": [
                      {
                        "packaging_id": null,
                        "packaging_name": null,
                        "description": "Desk xxx",
                        "length": 120,
                        "width": 60,
                        "height": 75,
                        "dimension_unit": 1,
                        "weight": 35,
                        "weight_unit": 2,
                        "value": null,
                        "qty": 2
                      }
                    ],
                    "raw_items": [],
                    "products": [],
                    "summary": {
                      "total_item_count": 2,
                      "total_group_count": 1,
                      "total_grouped_quantity": 2,
                      "total_product_quantity": 0
                    }
                  },
                  "price_recalculated": true,
                  "estimate_price_response": {
                    "shipping_fee": 25,
                    "pickup_fee": null,
                    "surcharges_total": 0,
                    "sub_total": 25,
                    "tax": {
                      "total_tax": 3.75
                    },
                    "total": 28.75,
                    "currency": "CAD"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.related-order-items.patch",
        "x-capability": "driver.delivery",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverOrdersOrderIdRelatedOrderItemsPatch"
      }
    },
    "/app/v1/driver/packagings": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get packaging types and packagings for the driver's service provider",
        "description": "Returns a list of packaging types with their associated packagings (predefined dimensions). Used in the driver app for selecting packaging when adding/editing items on storage and moving orders. Supports multi-language via the `language` parameter. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Language code for translated packaging names (e.g., 'en', 'zh', 'fr'). Defaults to 'en'.",
            "schema": {
              "type": "string",
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "allow_custom": {
                      "type": "boolean",
                      "description": "Whether the service provider allows custom packaging sizes"
                    },
                    "packaging_types": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "description": "Packaging type ID (0 = uncategorized)"
                          },
                          "name": {
                            "type": "string",
                            "description": "Translated packaging type name"
                          },
                          "packagings": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "name": {
                                  "type": "string",
                                  "description": "Translated packaging name"
                                },
                                "length": {
                                  "type": "number",
                                  "format": "float"
                                },
                                "width": {
                                  "type": "number",
                                  "format": "float"
                                },
                                "height": {
                                  "type": "number",
                                  "format": "float"
                                },
                                "dimension_unit": {
                                  "type": "integer",
                                  "description": "1=mm, 2=cm, 3=m, 4=inch"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "allow_custom": true,
                  "packaging_types": [
                    {
                      "id": 1,
                      "name": "Cardboard Boxes",
                      "packagings": [
                        {
                          "id": 1,
                          "name": "Small Box",
                          "length": 30,
                          "width": 20,
                          "height": 15,
                          "dimension_unit": 2
                        },
                        {
                          "id": 2,
                          "name": "Medium Box",
                          "length": 50,
                          "width": 40,
                          "height": 30,
                          "dimension_unit": 2
                        }
                      ]
                    },
                    {
                      "id": 2,
                      "name": "Furniture & Appliances",
                      "packagings": [
                        {
                          "id": 4,
                          "name": "Small Appliance Wrap",
                          "length": 60,
                          "width": 50,
                          "height": 40,
                          "dimension_unit": 2
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.packagings.get",
        "x-capability": "driver.delivery",
        "operationId": "driverPackagingsGet"
      }
    },
    "/app/v1/driver/unit-mappings": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get dimension and weight unit mappings",
        "description": "Returns the available dimension units (mm, cm, m, inch) and weight units (g, kg, oz, lb) with translated labels and accuracy values. Used by the driver app to populate unit dropdowns dynamically instead of hardcoding. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Language code for translated unit labels (e.g., 'en', 'zh', 'fr'). Defaults to 'en'.",
            "schema": {
              "type": "string",
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "dimension_units": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "value": {
                            "type": "integer",
                            "description": "Unit ID used in API requests"
                          },
                          "label": {
                            "type": "string",
                            "description": "Translated unit label"
                          },
                          "accuracy": {
                            "type": "integer",
                            "description": "Number of decimal places for this unit"
                          }
                        }
                      }
                    },
                    "weight_units": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "value": {
                            "type": "integer",
                            "description": "Unit ID used in API requests"
                          },
                          "label": {
                            "type": "string",
                            "description": "Translated unit label"
                          },
                          "accuracy": {
                            "type": "integer",
                            "description": "Number of decimal places for this unit"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "dimension_units": [
                    {
                      "value": 1,
                      "label": "mm",
                      "accuracy": 0
                    },
                    {
                      "value": 2,
                      "label": "cm",
                      "accuracy": 1
                    },
                    {
                      "value": 3,
                      "label": "m",
                      "accuracy": 3
                    },
                    {
                      "value": 4,
                      "label": "inch",
                      "accuracy": 3
                    }
                  ],
                  "weight_units": [
                    {
                      "value": 1,
                      "label": "g",
                      "accuracy": 0
                    },
                    {
                      "value": 2,
                      "label": "kg",
                      "accuracy": 3
                    },
                    {
                      "value": 3,
                      "label": "oz",
                      "accuracy": 1
                    },
                    {
                      "value": 4,
                      "label": "lb",
                      "accuracy": 3
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.unit-mappings.get",
        "x-capability": "driver.delivery",
        "operationId": "driverUnitMappingsGet"
      }
    },
    "/app/v1/driver/ref/{ref}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Find the driver's order by ref, id or tracking number",
        "operationId": "driverOrderByRef",
        "description": "The calling driver's order on one of their routes, found by the order's ref, its id, or a package tracking / external tracking number. Answers the order's columns plus operation_mode, routes_status_id and route_driver_status (the driver's own status on the route: 0 created, 1 started, 2 ended). An order that is not the driver's answers 404 with the not-found message. Recipient privacy (client setting, off by default): once the driver has ended the route, or the client's chosen number of days after the route date has passed, name, company_name, email and telephone are empty strings and the contact keys of shipping_from are blank; every key and the address stay. Driver apps only; needs driver.scan on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "ref",
            "schema": {
              "type": "string"
            },
            "required": true,
            "description": "Order ref, order id, tracking number or external tracking number"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "ref": {
                      "type": "string",
                      "nullable": true
                    },
                    "type": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string",
                      "nullable": true
                    },
                    "email": {
                      "type": "string",
                      "nullable": true
                    },
                    "telephone": {
                      "type": "string",
                      "nullable": true
                    },
                    "address_1": {
                      "type": "string"
                    },
                    "address_2": {
                      "type": "string",
                      "nullable": true
                    },
                    "city": {
                      "type": "string"
                    },
                    "province": {
                      "type": "string"
                    },
                    "postcode": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string"
                    },
                    "shipping_from": {
                      "type": "string",
                      "nullable": true,
                      "description": "JSON text of the pickup address"
                    },
                    "signature_option": {
                      "type": "integer"
                    },
                    "insurance_option": {
                      "type": "integer"
                    },
                    "orders_status_id": {
                      "type": "integer"
                    },
                    "route_id": {
                      "type": "integer"
                    },
                    "driver_id": {
                      "type": "integer"
                    },
                    "operation_mode": {
                      "type": "integer"
                    },
                    "routes_status_id": {
                      "type": "integer"
                    },
                    "route_driver_status": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No order of the driver matches",
            "content": {
              "application/json": {
                "example": {
                  "message": "No results found"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.ref.ref.get",
        "x-capability": "driver.scan",
        "security": [
          {
            "partnerAppToken": []
          }
        ]
      }
    },
    "/app/v1/driver/orders-notes/create": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Create an order note",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderNotesSave"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orderId": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "orderId": 12708,
                  "message": "Success"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders-notes.create.post",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrdersNotesCreate",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverOrdersNotesCreate"
      }
    },
    "/app/v1/driver/orders-notes/{orderId}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Get order notes",
        "parameters": [
          {
            "in": "path",
            "name": "orderId",
            "schema": {
              "type": "integer"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "notes": {
                        "type": "string"
                      },
                      "note_time": {
                        "type": "string"
                      },
                      "created_by": {
                        "type": "string"
                      }
                    }
                  }
                },
                "example": [
                  {
                    "id": 78,
                    "notes": "adsafdssa",
                    "note_time": "2020-10-01 06:35:32",
                    "created_by": "9397-2958 Quebec inc."
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders-notes.orderId.get",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrdersNotes",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverOrdersNotes"
      }
    },
    "/app/v1/driver/orders-files/{orderId}": {
      "get": {
        "summary": "GET /app/v1/driver/orders-files/{orderId}",
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.orders-files.orderId.get",
        "x-capability": "driver.delivery",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-graphql": "driverOrderFiles",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverOrderFiles"
      }
    },
    "/app/v1/driver/upload-pictures": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Upload order picture",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderPictureUpload"
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "orderId",
                  "type"
                ],
                "properties": {
                  "orderId": {
                    "type": "integer",
                    "example": 12708
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "photo",
                      "signature"
                    ],
                    "example": "photo"
                  },
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "A single file. Ignored when images[] is sent."
                  },
                  "images[]": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Several files in one request, at most 10. Each is stored as a separate order file."
                  },
                  "note": {
                    "type": "string",
                    "example": "left at door"
                  },
                  "gps_tracking_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "operation_event_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "tracking_event_id": {
                    "type": "integer",
                    "nullable": true
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "Id of the first stored file."
                    },
                    "orderId": {
                      "type": "integer"
                    },
                    "url": {
                      "type": "string",
                      "description": "Url of the first stored file."
                    },
                    "gps_tracking_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "operation_event_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "tracking_event_id": {
                      "type": "integer",
                      "nullable": true,
                      "description": "The tracking event the proof was tied to, or null when the order has no outcome yet (it is tied when the driver reports one)."
                    },
                    "message": {
                      "type": "string"
                    },
                    "files": {
                      "type": "array",
                      "description": "Every stored file, in the order it was sent. One entry for a single image.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "url": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "id": 2323,
                  "orderId": 12708,
                  "url": "https://admin.superroute.ca/storage/2020-08-09/12708_P_JklHTuSn5IiQmkX.jpeg",
                  "files": [
                    {
                      "id": 2323,
                      "url": "https://admin.superroute.ca/storage/2020-08-09/12708_P_JklHTuSn5IiQmkX.jpeg"
                    },
                    {
                      "id": 2324,
                      "url": "https://admin.superroute.ca/storage/2020-08-09/12708_P_Q3fYt9Lk2bXw7Rm.jpeg"
                    }
                  ],
                  "gps_tracking_id": null,
                  "operation_event_id": 456789,
                  "tracking_event_id": 123456,
                  "message": "Success"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request: missing orderId, type or image data, or more than 10 files in images[]. `message` is an array of reasons, worded in the language of the Accept-Language header."
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Stores a proof-of-delivery photo or signature for an order on the driver's current route. Send one file as `image` (multipart file, base64 string or `imageUrl`), or up to 10 files at once as `images[]` (multipart). Each file in `images[]` is stored as its own order file with the same note and event links. When `images[]` is present it takes precedence over `image`. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "x-route-name": "openapp.driver.upload-pictures.post",
        "x-capability": "driver.delivery",
        "x-graphql": "driverUploadPictures",
        "operationId": "driverUploadPictures"
      }
    },
    "/app/v1/driver/upload-pictures-from-urls": {
      "post": {
        "summary": "POST /app/v1/driver/upload-pictures-from-urls",
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.upload-pictures-from-urls.post",
        "x-capability": "driver.delivery",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverUploadPicturesFromUrlsPost"
      }
    },
    "/app/v1/driver/delete-pictures": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Delete order picture by orderfile Id",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderPictureDelete"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message": "Success"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "404": {
            "description": "Order Not Found"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.delete-pictures.post",
        "x-capability": "driver.delivery",
        "x-graphql": "driverDeletePictures",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverDeletePictures"
      }
    },
    "/app/v1/driver/update-deliver": {
      "post": {
        "summary": "POST /app/v1/driver/update-deliver",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "message": "Success"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          },
          "422": {
            "description": "Not completed: message, and pod_requirement (pod_pickup_photo_required, pod_geofence, pod_geofence_no_position) when a POD requirement is not met; a missing or wrong delivery PIN",
            "content": {
              "application/json": {
                "example": {
                  "message": "A photo is required to complete this pickup.",
                  "pod_requirement": "pod_pickup_photo_required"
                }
              }
            }
          }
        },
        "x-route-name": "openapp.driver.update-deliver.post",
        "x-capability": "driver.delivery",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-graphql": "driverUpdateDeliver",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverUpdateDeliver",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "route_id",
                  "order_id",
                  "latitude",
                  "longitude",
                  "status_code"
                ],
                "properties": {
                  "route_id": {
                    "type": "integer"
                  },
                  "order_id": {
                    "type": "integer"
                  },
                  "latitude": {
                    "type": "number",
                    "description": "The driver's position at completion"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "status_code": {
                    "type": "string",
                    "enum": [
                      "S",
                      "NR",
                      "RL",
                      "P",
                      "LST",
                      "RESET"
                    ],
                    "description": "S successful (picked up on a pickup stop), NR need rescheduled, RL reschedule later, P partial, LST package lost, RESET back to planned"
                  },
                  "photo_files": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Photos as files (JPEG, PNG or GIF, at most 2 MB each); they count toward the pickup photo requirement"
                  },
                  "photo_urls": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Photos already reachable at a URL, fetched and stored with the stop"
                  },
                  "signature_file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The signature as a file (JPEG or PNG, at most 2 MB)"
                  },
                  "signature_url": {
                    "type": "string"
                  },
                  "signature_note": {
                    "type": "string",
                    "description": "Who signed"
                  },
                  "return_reason_id": {
                    "type": "integer",
                    "description": "A reason from GET /app/v1/driver/return-reasons for a failed stop"
                  },
                  "captured_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the driver completed the stop, for a completion sent later"
                  },
                  "photo_url1": {
                    "type": "string",
                    "description": "Legacy single photo URL"
                  },
                  "photo_url2": {
                    "type": "string",
                    "description": "Legacy single photo URL"
                  },
                  "package_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "The packages handed over on a partial stop"
                  },
                  "delivery_pin": {
                    "type": "string",
                    "minLength": 6,
                    "maxLength": 6,
                    "description": "The recipient's six-digit delivery PIN when the order needs one"
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "route_id",
                  "order_id",
                  "latitude",
                  "longitude",
                  "status_code"
                ],
                "properties": {
                  "route_id": {
                    "type": "integer"
                  },
                  "order_id": {
                    "type": "integer"
                  },
                  "latitude": {
                    "type": "number",
                    "description": "The driver's position at completion"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "status_code": {
                    "type": "string",
                    "enum": [
                      "S",
                      "NR",
                      "RL",
                      "P",
                      "LST",
                      "RESET"
                    ],
                    "description": "S successful (picked up on a pickup stop), NR need rescheduled, RL reschedule later, P partial, LST package lost, RESET back to planned"
                  },
                  "photo_urls": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Photos already reachable at a URL, fetched and stored with the stop"
                  },
                  "signature_url": {
                    "type": "string"
                  },
                  "signature_note": {
                    "type": "string",
                    "description": "Who signed"
                  },
                  "return_reason_id": {
                    "type": "integer",
                    "description": "A reason from GET /app/v1/driver/return-reasons for a failed stop"
                  },
                  "captured_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the driver completed the stop, for a completion sent later"
                  },
                  "photo_url1": {
                    "type": "string",
                    "description": "Legacy single photo URL"
                  },
                  "photo_url2": {
                    "type": "string",
                    "description": "Legacy single photo URL"
                  },
                  "package_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "The packages handed over on a partial stop"
                  },
                  "delivery_pin": {
                    "type": "string",
                    "minLength": 6,
                    "maxLength": 6,
                    "description": "The recipient's six-digit delivery PIN when the order needs one"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/app/v1/driver/batch-update-deliver": {
      "post": {
        "summary": "POST /app/v1/driver/batch-update-deliver",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "message": "Success"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          },
          "422": {
            "description": "Not completed: message, and pod_requirement (pod_pickup_photo_required, pod_geofence, pod_geofence_no_position) when a POD requirement is not met; a missing or wrong delivery PIN",
            "content": {
              "application/json": {
                "example": {
                  "message": "A photo is required to complete this pickup.",
                  "pod_requirement": "pod_pickup_photo_required"
                }
              }
            }
          }
        },
        "x-route-name": "openapp.driver.batch-update-deliver.post",
        "x-capability": "driver.delivery",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-graphql": "driverBatchUpdateDeliver",
        "description": "Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "operationId": "driverBatchUpdateDeliver",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "route_id",
                  "order_ids",
                  "latitude",
                  "longitude",
                  "status_code"
                ],
                "properties": {
                  "route_id": {
                    "type": "integer"
                  },
                  "order_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 1
                  },
                  "latitude": {
                    "type": "number",
                    "description": "The driver's position at completion"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "status_code": {
                    "type": "string",
                    "enum": [
                      "S",
                      "NR",
                      "RL",
                      "P",
                      "LST",
                      "RESET"
                    ],
                    "description": "S successful (picked up on a pickup stop), NR need rescheduled, RL reschedule later, P partial, LST package lost, RESET back to planned"
                  },
                  "photo_files": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Photos as files (JPEG, PNG or GIF, at most 2 MB each); they count toward the pickup photo requirement"
                  },
                  "photo_urls": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Photos already reachable at a URL, fetched and stored with the stop"
                  },
                  "signature_file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The signature as a file (JPEG or PNG, at most 2 MB)"
                  },
                  "signature_url": {
                    "type": "string"
                  },
                  "signature_note": {
                    "type": "string",
                    "description": "Who signed"
                  },
                  "return_reason_id": {
                    "type": "integer",
                    "description": "A reason from GET /app/v1/driver/return-reasons for a failed stop"
                  },
                  "captured_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the driver completed the stop, for a completion sent later"
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "route_id",
                  "order_ids",
                  "latitude",
                  "longitude",
                  "status_code"
                ],
                "properties": {
                  "route_id": {
                    "type": "integer"
                  },
                  "order_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 1
                  },
                  "latitude": {
                    "type": "number",
                    "description": "The driver's position at completion"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "status_code": {
                    "type": "string",
                    "enum": [
                      "S",
                      "NR",
                      "RL",
                      "P",
                      "LST",
                      "RESET"
                    ],
                    "description": "S successful (picked up on a pickup stop), NR need rescheduled, RL reschedule later, P partial, LST package lost, RESET back to planned"
                  },
                  "photo_urls": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Photos already reachable at a URL, fetched and stored with the stop"
                  },
                  "signature_url": {
                    "type": "string"
                  },
                  "signature_note": {
                    "type": "string",
                    "description": "Who signed"
                  },
                  "return_reason_id": {
                    "type": "integer",
                    "description": "A reason from GET /app/v1/driver/return-reasons for a failed stop"
                  },
                  "captured_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the driver completed the stop, for a completion sent later"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/app/v1/driver/sms/templates": {
      "get": {
        "summary": "GET /app/v1/driver/sms/templates",
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.sms.templates.get",
        "x-capability": "driver.sms",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-graphql": "driverSmsTemplates",
        "description": "Driver apps only; needs driver.sms on the token. Answered exactly as the internal driver route.",
        "operationId": "driverSmsTemplates"
      }
    },
    "/app/v1/driver/sms/success-content/order/{id}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Delivered message text for an order",
        "operationId": "driverSmsSuccessContent",
        "description": "The text of the business's Delivered Success message for the order, in the order's notification language, with its placeholders filled (falls back to the built-in wording when the business has none). A driver gets it only for an order they are delivering or created; any other order answers 404 with the not-found message, an order of another business 401. No text, or recipient privacy in effect (client setting, off by default: the driver has ended the route, or the chosen number of days after the route date has passed), answers 404 with content ''. Driver apps only; needs driver.sms on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "content": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "content": "Dear Jane, your package has been delivered to 1 Main St, Montreal, QC, H1H 1H1"
                }
              }
            }
          },
          "404": {
            "description": "No text, or the order is not the driver's",
            "content": {
              "application/json": {
                "example": {
                  "content": ""
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.sms.success-content.order.id.get",
        "x-capability": "driver.sms",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-graphql": "driverSmsSuccessContent"
      }
    },
    "/app/v1/driver/duty": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Driver duty status and pending offers",
        "description": "Dispatch Options → driver_duty. Returns whether the feature is enabled for the driver's business, the driver's on-duty state and the auto-assign offers awaiting an answer. With the feature disabled on_duty is always true and pending_offers empty. Driver apps only; needs driver.duty on the token. Answered exactly as the internal driver route.",
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "feature_enabled": true,
                  "on_duty": true,
                  "on_duty_changed_at": "2026-08-17 08:00:00",
                  "require_accept": true,
                  "response_timeout_minutes": 5,
                  "pending_offers": [
                    {
                      "offer_id": 31,
                      "subject_type": "order",
                      "subject_id": 555,
                      "order_id": 555,
                      "order_ref": "SR100000555",
                      "order_type": "D",
                      "address": "12 Main St, Montreal",
                      "offered_at": "2026-08-17 10:00:00",
                      "expires_at": "2026-08-17 10:05:00"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.duty.get",
        "x-capability": "driver.duty",
        "x-graphql": "driverDuty",
        "operationId": "driverDuty"
      },
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Go on / off duty",
        "description": "Sets the calling driver on or off duty. Only on-duty drivers receive auto-assigned work when the business enabled dispatch_to_on_duty_only. Returns 409 when the feature is disabled for the business. Driver apps only; needs driver.duty on the token. Answered exactly as the internal driver route.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "on_duty": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "feature_enabled": true,
                  "on_duty": true,
                  "on_duty_changed_at": "2026-08-17 08:00:00",
                  "require_accept": true,
                  "response_timeout_minutes": 5,
                  "pending_offers": [
                    {
                      "offer_id": 31,
                      "subject_type": "order",
                      "subject_id": 555,
                      "order_id": 555,
                      "order_ref": "SR100000555",
                      "order_type": "D",
                      "address": "12 Main St, Montreal",
                      "offered_at": "2026-08-17 10:00:00",
                      "expires_at": "2026-08-17 10:05:00"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found"
          },
          "409": {
            "description": "Feature disabled for this business"
          },
          "422": {
            "description": "on_duty missing"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.duty.post",
        "x-capability": "driver.duty",
        "x-graphql": "driverDutyUpdate",
        "operationId": "driverDutyUpdate"
      }
    },
    "/app/v1/driver/assignments/pending": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Pending auto-assign offers",
        "description": "Auto-assigned orders still waiting for the driver's accept / reject (Dispatch Options → driver_duty with require_accept). Driver apps only; needs driver.duty on the token. Answered exactly as the internal driver route.",
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "pending_offers": [
                    {
                      "offer_id": 31,
                      "subject_type": "order",
                      "subject_id": 555,
                      "order_id": 555,
                      "order_ref": "SR100000555",
                      "order_type": "D",
                      "address": "12 Main St, Montreal",
                      "offered_at": "2026-08-17 10:00:00",
                      "expires_at": "2026-08-17 10:05:00"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.assignments.pending.get",
        "x-capability": "driver.duty",
        "operationId": "driverAssignmentsPendingGet"
      }
    },
    "/app/v1/driver/orders/{orderId}/accept": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Accept an assigned order",
        "description": "Confirms an auto-assigned order. Accepting work that was planned by a dispatcher is a harmless no-op. Driver apps only; needs driver.duty on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "action": "accepted",
                  "released": false
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Order not found"
          },
          "409": {
            "description": "Feature disabled, or the order is not assigned to this driver"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.accept.post",
        "x-capability": "driver.duty",
        "x-graphql": "driverAssignmentRespond",
        "operationId": "driverAssignmentRespond"
      }
    },
    "/app/v1/driver/orders/{orderId}/reject": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Reject an assigned order",
        "description": "Rejects an auto-assigned order: the work is released back to the pool (instant orders are revoked, route orders removed from the driver's route) and, per the business setting, re-queued to the orchestrator or held for the dispatcher. Rejecting dispatcher-planned work is only recorded (released=false). Driver apps only; needs driver.duty on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "example": {
                "reason": "Too far away"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rejected",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "action": "rejected",
                  "released": true
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Order not found"
          },
          "409": {
            "description": "Feature disabled, or the order is not assigned to this driver"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.reject.post",
        "x-capability": "driver.duty",
        "operationId": "driverOrdersOrderIdRejectPost"
      }
    },
    "/app/v1/driver/earnings": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Driver earnings summary",
        "description": "Delivered orders, tips collected and an estimate of the pay the business payroll rule yields for the period (opt-in family delivery_tips with driver_earnings_visible; 409 otherwise). period = today | yesterday | week | month | custom (from/to, max 92 days). Driver apps only; needs driver.earnings on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "today"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "feature_enabled": true,
                  "period": "today",
                  "from": "2026-08-17 00:00:00",
                  "to": "2026-08-17 23:59:59",
                  "delivered_orders": 12,
                  "tips_total": 34.5,
                  "tips_pass_through_pct": 100,
                  "tips_driver_share": 34.5,
                  "estimated_pay": 118.5,
                  "estimated_pay_items": [
                    {
                      "type": "per_delivery",
                      "name": "Per Delivery",
                      "rate": 7,
                      "quantity": 12,
                      "subtotal": 84
                    },
                    {
                      "type": "tip_pass_through",
                      "name": "Tips pass-through (%)",
                      "rate": 100,
                      "quantity": 34.5,
                      "subtotal": 34.5
                    }
                  ],
                  "currency": "CAD",
                  "has_payroll_rule": true
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found"
          },
          "409": {
            "description": "Earnings view not enabled"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.earnings.get",
        "x-capability": "driver.earnings",
        "x-graphql": "driverEarnings",
        "operationId": "driverEarnings"
      }
    },
    "/app/v1/driver/orders/{orderId}/cash-collected": {
      "post": {
        "tags": [
          "Dispatch Options"
        ],
        "summary": "Driver records cash collected on an order (payroll v2)",
        "description": "Cash-collected settlement (opt-in family payroll_v2 with cash_settlement; 409 while off or storage not migrated). Payroll generation nets the collected cash out of the driver's pay (payment_after_cash). Send amount null to clear. Driver accounts; the order must be assigned to the driver. Driver apps only; needs driver.cash on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "amount": 42.5
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recorded",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "order_id": 555,
                  "cash_collected": 42.5
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "404": {
            "description": "Order not found"
          },
          "409": {
            "description": "Feature disabled or storage not migrated"
          },
          "422": {
            "description": "Amount out of range"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.cash-collected.post",
        "x-capability": "driver.cash",
        "x-graphql": "driverOrderCashCollected",
        "operationId": "driverOrderCashCollected"
      }
    },
    "/app/v1/driver/pod-requirements": {
      "get": {
        "tags": [
          "Dispatch Options"
        ],
        "summary": "POD requirements at stop completion (driver app)",
        "description": "Dispatch Options → pod_extras. Tells the app what to collect before completing a stop. While off every flag is false and geofence_m is 0. When on, POST /v1/driver/update-deliver answers 422 with pod_requirement = pod_pickup_photo_required | pod_geofence | pod_geofence_no_position when a requirement is not met. age_verification_required, item_check_required and geofence_allow_override are always false (not offered); the keys stay for compatibility. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "enabled": true,
                  "age_verification_required": false,
                  "pickup_photo_required": true,
                  "item_check_required": false,
                  "geofence_m": 150,
                  "geofence_allow_override": false
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.pod-requirements.get",
        "x-capability": "driver.delivery",
        "x-graphql": "driverPodRequirements",
        "operationId": "driverPodRequirements"
      }
    },
    "/app/v1/driver/sms/fail-content/order/{id}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Delivery failed message text for an order",
        "operationId": "driverSmsFailContent",
        "description": "The text of the business's Delivered Fail message for the order, in the order's notification language, with its placeholders filled (falls back to the built-in wording when the business has none). A driver gets it only for an order they are delivering or created; any other order answers 404 with the not-found message, an order of another business 401. No text, or recipient privacy in effect (client setting, off by default: the driver has ended the route, or the chosen number of days after the route date has passed), answers 404 with content ''. Driver apps only; needs driver.sms on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "content": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No text, or the order is not the driver's",
            "content": {
              "application/json": {
                "example": {
                  "content": ""
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.sms.fail-content.order.id.get",
        "x-capability": "driver.sms",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-graphql": "driverSmsFailContent"
      }
    },
    "/app/v1/driver/sms/template/{templateId}/order/{id}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Message text of a template for an order",
        "operationId": "driverSmsTemplateContent",
        "description": "The text of one SMS template (from GET /v1/driver/sms/templates) for the order, in the order's notification language, with its placeholders filled. A driver gets it only for an order they are delivering or created; any other order, an unknown template or a template without the order's language answers 404 with a message, an order of another business 401. Recipient privacy in effect (client setting, off by default: the driver has ended the route, or the chosen number of days after the route date has passed) answers 404 with content ''. Driver apps only; needs driver.sms on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "templateId",
            "schema": {
              "type": "integer"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "required": true,
            "description": "Order id"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "content": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found, or the order is not the driver's",
            "content": {
              "application/json": {
                "example": {
                  "message": "Not Found"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.sms.template.templateId.order.id.get",
        "x-capability": "driver.sms",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-graphql": "driverSmsTemplateContent"
      }
    },
    "/app/v1/driver/profile": {
      "get": {
        "operationId": "driverProfileShow",
        "tags": [
          "Driver"
        ],
        "summary": "get driver profile",
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "data": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "vehicle_type": {
                            "type": "string"
                          },
                          "address": {
                            "type": "string"
                          },
                          "address_2": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "province": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          },
                          "postcode": {
                            "type": "string"
                          },
                          "telephone": {
                            "type": "string"
                          },
                          "tracking_number_prefix": {
                            "type": "string",
                            "nullable": true
                          },
                          "alias": {
                            "type": "string"
                          },
                          "users_info_id": {
                            "type": "integer"
                          },
                          "business_id": {
                            "type": "integer"
                          },
                          "capacity": {
                            "type": "string",
                            "nullable": true
                          },
                          "business_name": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "territory_id": {
                            "type": "integer"
                          },
                          "start_location_id": {
                            "type": "string",
                            "nullable": true
                          },
                          "end_location_id": {
                            "type": "string",
                            "nullable": true
                          },
                          "gps_tracking": {
                            "type": "integer"
                          },
                          "gps_device_type": {
                            "type": "string"
                          },
                          "gps_identifier": {
                            "type": "string"
                          },
                          "status": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                },
                "example": [
                  {
                    "data": {
                      "id": 1,
                      "name": "driver003_1",
                      "email": "driver003@example.com",
                      "vehicle_type": "1 (1: Car, 2: Truck, 3: Motorcycle, 4: Bicycle 5:Pedestrian)",
                      "address": "",
                      "address_2": "",
                      "city": "",
                      "province": "",
                      "country": "Canada",
                      "postcode": "",
                      "telephone": "5140000003",
                      "tracking_number_prefix": null,
                      "alias": "alias0003_1",
                      "users_info_id": 3,
                      "business_id": 2,
                      "capacity": null,
                      "business_name": "Client Example",
                      "language": "en",
                      "territory_id": 1,
                      "start_location_id": null,
                      "end_location_id": null,
                      "gps_tracking": 0,
                      "gps_device_type": "1",
                      "gps_identifier": "",
                      "status": 1
                    }
                  }
                ]
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.profile.get",
        "x-capability": "driver.routes",
        "x-graphql": "driverProfile",
        "description": "Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route."
      },
      "put": {
        "operationId": "driverProfileUpdate",
        "tags": [
          "Driver"
        ],
        "summary": "update driver profile",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "alias": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "vehicle_type": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "telephone": {
                    "type": "string"
                  },
                  "start_location_id": {
                    "type": "integer"
                  },
                  "end_location_id": {
                    "type": "integer"
                  },
                  "language": {
                    "type": "string"
                  },
                  "capacity": {
                    "type": "integer"
                  },
                  "territory_id": {
                    "type": "integer"
                  },
                  "status": {
                    "type": "integer"
                  }
                }
              },
              "examples": {
                "English": {
                  "value": {
                    "name": "driver003_1",
                    "alias": "alias0003_1",
                    "email": "driver003@example.com",
                    "vehicle_type": "1 (1: Car, 2: Truck, 3: Motorcycle, 4: Bicycle 5:Pedestrian nullable,default 1)",
                    "password": "12345678",
                    "telephone": "5140000003",
                    "start_location_id": 1,
                    "end_location_id": 1,
                    "language": "en",
                    "capacity": 60,
                    "territory_id": 1,
                    "status": 1
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "business_id": {
                        "type": "integer"
                      },
                      "Email": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "status": {
                        "type": "integer"
                      },
                      "alias": {
                        "type": "string"
                      },
                      "telephone": {
                        "type": "string"
                      },
                      "language": {
                        "type": "string"
                      },
                      "capacity": {
                        "type": "string",
                        "nullable": true
                      },
                      "territory_id": {
                        "type": "integer"
                      },
                      "start_location_id": {
                        "type": "string",
                        "nullable": true
                      },
                      "end_location_id": {
                        "type": "string",
                        "nullable": true
                      }
                    }
                  }
                },
                "example": [
                  {
                    "id": 1,
                    "business_id": 1,
                    "Email": "driver001@example.com",
                    "name": "driver001",
                    "status": 1,
                    "alias": "alias0001",
                    "telephone": "5140000012",
                    "language": "en",
                    "capacity": null,
                    "territory_id": 1,
                    "start_location_id": null,
                    "end_location_id": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.profile.put",
        "x-capability": "driver.routes",
        "description": "Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route."
      }
    },
    "/app/v1/driver/create-route": {
      "post": {
        "summary": "Create a new route by driver",
        "description": "Allows a driver to create a new delivery route if authorized. Driver apps only; needs driver.route_edit on the token. Answered exactly as the internal driver route.",
        "tags": [
          "Driver"
        ],
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "description": "Optional name field to customize the route name",
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Custom route name (optional)",
                    "example": "route_001"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Route created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "route_id": {
                      "type": "integer",
                      "example": 123
                    },
                    "route_driver_id": {
                      "type": "integer",
                      "example": 456
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Creation failed due to server or data error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Exception message"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "x-route-name": "openapp.driver.create-route.post",
        "x-capability": "driver.route_edit",
        "x-graphql": "driverCreateRoute",
        "operationId": "driverCreateRoute"
      }
    },
    "/app/v1/driver/orders": {
      "get": {
        "summary": "Get Orders",
        "description": "Retrieve a list of orders filtered by optional parameters such as status, id, unassigned flag, and pagination. Driver apps only; needs driver.routes on the token. Answered exactly as the internal driver route.",
        "tags": [
          "Driver"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by order status ID",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "id",
            "in": "query",
            "description": "Filter by specific order ID",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "unassigned",
            "in": "query",
            "description": "Set to 1 to filter only unassigned orders (no driver and no route)",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Number of items per page",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful order list response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Successful"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.get",
        "x-capability": "driver.routes",
        "operationId": "driverOrdersGet"
      }
    },
    "/app/v1/driver/optimize-route": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "optimize route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OptimizeRouteForDriver"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Optimize job is running in background"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.optimize-route.post",
        "x-capability": "driver.route_edit",
        "x-graphql": "driverOptimizeRoute",
        "description": "Driver apps only; needs driver.route_edit on the token. Answered exactly as the internal driver route.",
        "operationId": "driverOptimizeRoute"
      }
    },
    "/app/v1/driver/kiosk-receiving-packages": {
      "get": {
        "summary": "Get kiosk receiving area package count",
        "description": "Query how many receiving packages exist at a kiosk pickup location. The driver must be assigned to the route, the route must not be ended, and the order must be a kiosk pickup order (related_order_type = 6). Driver apps only; needs driver.kiosk on the token. Answered exactly as the internal driver route.",
        "tags": [
          "Driver"
        ],
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "route_id",
            "in": "query",
            "description": "The route ID that contains the kiosk pickup order",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 100
          },
          {
            "name": "order_id",
            "in": "query",
            "description": "The kiosk pickup order ID on the route",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 5000
          }
        ],
        "responses": {
          "200": {
            "description": "Receiving area package count retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "location_id": {
                      "type": "integer",
                      "description": "The addressbook ID of the kiosk location",
                      "example": 42
                    },
                    "location_name": {
                      "type": "string",
                      "description": "Name of the kiosk location",
                      "example": "Kiosk Downtown"
                    },
                    "receiving_package_count": {
                      "type": "integer",
                      "description": "Total quantity of packages in the receiving area at this kiosk",
                      "example": 15
                    }
                  }
                },
                "example": {
                  "result": true,
                  "location_id": 42,
                  "location_name": "Kiosk Downtown",
                  "receiving_package_count": 15
                }
              }
            }
          },
          "400": {
            "description": "Validation or business logic error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "description": "Specific error reason"
                    }
                  }
                },
                "examples": {
                  "order_not_on_route": {
                    "summary": "Order is not on the specified route",
                    "value": {
                      "result": false,
                      "message": "Order is not assigned to this route"
                    }
                  },
                  "route_not_assigned": {
                    "summary": "Route is not assigned to this driver",
                    "value": {
                      "result": false,
                      "message": "Route is not assigned to this driver"
                    }
                  },
                  "route_ended": {
                    "summary": "Route has already ended",
                    "value": {
                      "result": false,
                      "message": "Route has already ended"
                    }
                  },
                  "not_kiosk_pickup": {
                    "summary": "Order is not a kiosk pickup type",
                    "value": {
                      "result": false,
                      "message": "Order is not a kiosk pickup order"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.kiosk-receiving-packages.get",
        "x-capability": "driver.kiosk",
        "x-graphql": "driverKioskReceivingPackages",
        "operationId": "driverKioskReceivingPackages"
      }
    },
    "/app/v1/driver/kiosk-receive-package": {
      "post": {
        "summary": "Scan and receive an awaiting-processing package from kiosk receiving area",
        "description": "Driver scans a code at a kiosk location and receives a single awaiting-processing package from the receiving area onto their vehicle inventory. The driver must be assigned to the route, the route must not be ended, and the order must be a kiosk pickup order (related_order_type = 6). Supports every customer-dropped type: returns, express drop-offs and storage drop-offs. The code may be a return code, a reference number, or the package's own unique code. Plain delivery packages are intentionally excluded. Driver apps only; needs driver.kiosk on the token. Answered exactly as the internal driver route.",
        "tags": [
          "Driver"
        ],
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "route_id",
                  "order_id",
                  "scan_code"
                ],
                "properties": {
                  "route_id": {
                    "type": "integer",
                    "description": "The route ID that contains the kiosk pickup order",
                    "example": 100
                  },
                  "order_id": {
                    "type": "integer",
                    "description": "The kiosk pickup order ID on the route",
                    "example": 5000
                  },
                  "scan_code": {
                    "type": "string",
                    "description": "The code to scan: a return code, reference number, or the package's own unique code",
                    "example": "ABC123"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Package received successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Package received successfully"
                    },
                    "inventory_id": {
                      "type": "integer",
                      "description": "The inventory record ID now assigned to the driver",
                      "example": 50
                    },
                    "inventory_type": {
                      "type": "integer",
                      "description": "Inventory type of the received package (4 = Return, 6 = Express Package, 3 = Storage Package)",
                      "example": 4
                    },
                    "return_request": {
                      "type": "object",
                      "description": "Present only when the received package is a return",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "example": 10
                        },
                        "return_code": {
                          "type": "string",
                          "example": "ABC123"
                        },
                        "reference_number": {
                          "type": "string",
                          "example": "REF-001"
                        },
                        "status": {
                          "type": "integer",
                          "example": 5
                        },
                        "original_order_id": {
                          "type": "integer",
                          "example": 200
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Package received successfully",
                  "inventory_id": 50,
                  "inventory_type": 4,
                  "return_request": {
                    "id": 10,
                    "return_code": "ABC123",
                    "reference_number": "REF-001",
                    "status": 5,
                    "original_order_id": 200
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation or business logic error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "description": "Specific error reason"
                    }
                  }
                },
                "examples": {
                  "return_not_found": {
                    "summary": "Return request not found or wrong status",
                    "value": {
                      "result": false,
                      "message": "Return request not found or not in dropped-off status"
                    }
                  },
                  "not_in_receiving_area": {
                    "summary": "Return package not at this kiosk location",
                    "value": {
                      "result": false,
                      "message": "Return package not found in the receiving area at this location"
                    }
                  },
                  "order_not_on_route": {
                    "summary": "Order is not on the specified route",
                    "value": {
                      "result": false,
                      "message": "Order is not assigned to this route"
                    }
                  },
                  "route_not_assigned": {
                    "summary": "Route is not assigned to this driver",
                    "value": {
                      "result": false,
                      "message": "Route is not assigned to this driver"
                    }
                  },
                  "route_ended": {
                    "summary": "Route has already ended",
                    "value": {
                      "result": false,
                      "message": "Route has already ended"
                    }
                  },
                  "not_kiosk_pickup": {
                    "summary": "Order is not a kiosk pickup type",
                    "value": {
                      "result": false,
                      "message": "Order is not a kiosk pickup order"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Package has already been received",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Package has already been received"
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "Package has already been received"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.kiosk-receive-package.post",
        "x-capability": "driver.kiosk",
        "x-graphql": "driverKioskReceivePackage",
        "operationId": "driverKioskReceivePackage"
      }
    },
    "/app/v1/driver/availability": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Current availability (online, heartbeat, load)",
        "description": "The signed-in driver's availability record — every driver, not only Instant riders. `online` is the switch; `heartbeat_stale` is true when the app has not checked in for 20 minutes; `active_orders` counts in-flight instant orders. Drivers who never toggled are reported from the legacy drivers.task_online default (online). Driver apps only; needs driver.availability on the token. Answered exactly as the internal driver route.",
        "operationId": "driverAvailabilityShow",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "driver_id": {
                          "type": "integer",
                          "example": 12
                        },
                        "online": {
                          "type": "boolean",
                          "example": true
                        },
                        "task_online": {
                          "type": "boolean",
                          "example": true,
                          "description": "Legacy alias of `online`."
                        },
                        "accepting_offers": {
                          "type": "boolean",
                          "example": true
                        },
                        "max_concurrent": {
                          "type": "integer",
                          "nullable": true,
                          "example": null,
                          "description": "Personal in-flight cap; null = platform default."
                        },
                        "vehicle_type": {
                          "type": "string",
                          "nullable": true,
                          "example": "bike"
                        },
                        "last_heartbeat_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "heartbeat_stale": {
                          "type": "boolean",
                          "example": false,
                          "description": "True when no heartbeat in the last 20 minutes."
                        },
                        "position": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "lat": {
                              "type": "number"
                            },
                            "lng": {
                              "type": "number"
                            },
                            "source": {
                              "type": "string",
                              "enum": [
                                "app",
                                "tracker"
                              ]
                            },
                            "recorded_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "active_orders": {
                          "type": "integer",
                          "example": 1,
                          "description": "In-flight instant orders held by this driver."
                        },
                        "online_changed_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Online",
                  "data": {
                    "driver_id": 12,
                    "online": true,
                    "task_online": true,
                    "accepting_offers": true,
                    "max_concurrent": null,
                    "vehicle_type": "bike",
                    "last_heartbeat_at": "2026-08-26T14:03:11+00:00",
                    "heartbeat_stale": false,
                    "position": {
                      "lat": 45.5019,
                      "lng": -73.5674,
                      "source": "app",
                      "recorded_at": "2026-08-26T14:03:11+00:00"
                    },
                    "active_orders": 1,
                    "online_changed_at": "2026-08-26T13:00:00+00:00"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.availability.get",
        "x-capability": "driver.availability",
        "x-graphql": "driverAvailability"
      },
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Go online/offline or send a heartbeat",
        "description": "Send `online` to flip the switch (also written to drivers.task_online for legacy readers). Without `online` the call is a heartbeat: it refreshes `last_heartbeat_at` and applies any preference sent. `lat`/`lng` (together) record the phone's position and append it to the dispatcher's live map history. Recommended: one heartbeat with position every 60 s while online. Driver apps only; needs driver.availability on the token. Answered exactly as the internal driver route.",
        "operationId": "driverAvailabilityUpdate",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "online": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Omit for a heartbeat only."
                  },
                  "accepting_offers": {
                    "type": "boolean",
                    "nullable": true
                  },
                  "max_concurrent": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 0,
                    "maximum": 50,
                    "description": "0 or null clears the personal cap."
                  },
                  "vehicle_type": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 32
                  },
                  "lat": {
                    "type": "number",
                    "nullable": true,
                    "minimum": -90,
                    "maximum": 90
                  },
                  "lng": {
                    "type": "number",
                    "nullable": true,
                    "minimum": -180,
                    "maximum": 180
                  }
                }
              },
              "example": {
                "online": true,
                "accepting_offers": true,
                "vehicle_type": "bike",
                "lat": 45.5019,
                "lng": -73.5674
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "driver_id": {
                          "type": "integer",
                          "example": 12
                        },
                        "online": {
                          "type": "boolean",
                          "example": true
                        },
                        "task_online": {
                          "type": "boolean",
                          "example": true,
                          "description": "Legacy alias of `online`."
                        },
                        "accepting_offers": {
                          "type": "boolean",
                          "example": true
                        },
                        "max_concurrent": {
                          "type": "integer",
                          "nullable": true,
                          "example": null,
                          "description": "Personal in-flight cap; null = platform default."
                        },
                        "vehicle_type": {
                          "type": "string",
                          "nullable": true,
                          "example": "bike"
                        },
                        "last_heartbeat_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "heartbeat_stale": {
                          "type": "boolean",
                          "example": false,
                          "description": "True when no heartbeat in the last 20 minutes."
                        },
                        "position": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "lat": {
                              "type": "number"
                            },
                            "lng": {
                              "type": "number"
                            },
                            "source": {
                              "type": "string",
                              "enum": [
                                "app",
                                "tracker"
                              ]
                            },
                            "recorded_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "active_orders": {
                          "type": "integer",
                          "example": 1,
                          "description": "In-flight instant orders held by this driver."
                        },
                        "online_changed_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Online",
                  "data": {
                    "driver_id": 12,
                    "online": true,
                    "task_online": true,
                    "accepting_offers": true,
                    "max_concurrent": null,
                    "vehicle_type": "bike",
                    "last_heartbeat_at": "2026-08-26T14:03:11+00:00",
                    "heartbeat_stale": false,
                    "position": {
                      "lat": 45.5019,
                      "lng": -73.5674,
                      "source": "app",
                      "recorded_at": "2026-08-26T14:03:11+00:00"
                    },
                    "active_orders": 1,
                    "online_changed_at": "2026-08-26T13:00:00+00:00"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "422": {
            "description": "Validation error (e.g. lat without lng)."
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.availability.post",
        "x-capability": "driver.availability",
        "x-graphql": "driverAvailabilitySet"
      }
    },
    "/app/v1/driver/pool/orders": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Regular orders in the driver pool",
        "description": "Orders a dispatcher published to the driver pool (docs/ON-DEMAND-DISPATCH-ENHANCEMENT-PLAN.md M3): unrouted, unassigned, non-instant orders of the driver's business in a plannable status. `distance_km` is filled when the app has sent a position (POST /v1/driver/availability). Empty with `meta.enabled=false` when the business has not switched the pool on. The instant rider pool is separate: /v1/rider/available-orders. Driver apps only; needs driver.pool on the token. Answered exactly as the internal driver route.",
        "operationId": "driverPoolOrders",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "order_id": {
                            "type": "integer"
                          },
                          "ref": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string"
                          },
                          "status_id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "address": {
                            "type": "string"
                          },
                          "latitude": {
                            "type": "number"
                          },
                          "longitude": {
                            "type": "number"
                          },
                          "packages": {
                            "type": "integer"
                          },
                          "time_window_start": {
                            "type": "string",
                            "nullable": true
                          },
                          "time_window_end": {
                            "type": "string",
                            "nullable": true
                          },
                          "distance_km": {
                            "type": "number"
                          },
                          "published_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "enabled": {
                          "type": "boolean"
                        },
                        "server_time": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Successful",
                  "data": [
                    {
                      "order_id": 7001,
                      "ref": "ORD-7001",
                      "type": "D",
                      "status_id": 2,
                      "name": "Ann Lee",
                      "address": "2 Elm St, Toronto M5V 1A1",
                      "latitude": 43.6452,
                      "longitude": -79.3806,
                      "packages": 1,
                      "time_window_start": null,
                      "time_window_end": null,
                      "distance_km": 2.4,
                      "published_at": "2026-08-26T14:00:00+00:00"
                    }
                  ],
                  "meta": {
                    "total": 1,
                    "enabled": true,
                    "server_time": "2026-08-26T14:05:00+00:00"
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.pool.orders.get",
        "x-capability": "driver.pool",
        "x-graphql": "driverPoolOrders"
      }
    },
    "/app/v1/driver/pool/orders/{orderId}/claim": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Claim a pool order onto today's route",
        "description": "Atomically takes the order (the row is locked; a second driver gets 409) and appends it as the next stop of the driver's route for today — the route given in `route_id` (must be the driver's own, today), else their latest route for today, else a new route when the business allows drivers to create routes. The order moves to Already Planned and leaves the pool. Driver apps only; needs driver.pool on the token. Answered exactly as the internal driver route.",
        "operationId": "driverPoolClaim",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "orderId",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "route_id": {
                    "type": "integer",
                    "nullable": true
                  }
                }
              },
              "example": {
                "route_id": null
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Claimed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "result": {
                          "type": "string"
                        },
                        "order_id": {
                          "type": "integer"
                        },
                        "route_id": {
                          "type": "integer"
                        },
                        "stop_number": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "message": "Claimed",
                  "data": {
                    "result": "ok",
                    "order_id": 7001,
                    "route_id": 23565,
                    "stop_number": 4
                  }
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          },
          "409": {
            "description": "`gone` — taken by someone else or withdrawn; `no_route` — no route today and drivers may not create one.",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Order is no longer available",
                  "data": {
                    "result": "gone",
                    "order_id": null,
                    "route_id": null,
                    "stop_number": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.driver.pool.orders.orderId.claim.post",
        "x-capability": "driver.pool",
        "x-graphql": "driverPoolClaim"
      }
    },
    "/app/v1/driver/pickup-order/{ref}": {
      "post": {
        "tags": [
          "Driver"
        ],
        "summary": "Pickup scan by order or package identifier",
        "operationId": "driverPickupOrder",
        "description": "A driver marks an order picked up. A staff account allowed to use the driver app receives the order into its warehouse instead (same rules as the web receive page); an order that is already delivered is then received only with confirm_delivered=true and a reason. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "in": "path",
            "name": "ref",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Order id, order ref, package id, package ref, tracking number or external tracking number."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "latitude": {
                    "type": "number",
                    "nullable": true
                  },
                  "longitude": {
                    "type": "number",
                    "nullable": true
                  },
                  "confirm_delivered": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Staff scan only. Optional. Set to true to receive an order that is already delivered (Successful). Requires reason. Without it, a delivered order is refused with code order_delivered and nothing changes."
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 500,
                    "description": "Staff scan only. Optional. Why a delivered order is received back, for example refused by the recipient. Required together with confirm_delivered=true. Recorded on the order's operation history."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scan processed. result=false carries the refusal message; for a delivered order code=order_delivered and confirmation_required=true are added.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "id": {
                      "description": "Package id (staff scan, may carry the channel name) or order id"
                    },
                    "ref": {
                      "type": "string"
                    },
                    "full_address": {
                      "type": "string"
                    },
                    "status": {
                      "description": "Order status name (staff scan) or status"
                    },
                    "code": {
                      "type": "string",
                      "nullable": true,
                      "description": "Added additively. Present only on refusal of a delivered order: order_delivered."
                    },
                    "confirmation_required": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "Added additively. Present only on refusal of a delivered order: true. Send the request again with confirm_delivered=true and a reason."
                    }
                  }
                },
                "example": {
                  "result": false,
                  "message": "The order is already delivered. Confirm and enter a reason to receive it.",
                  "id": "1001",
                  "ref": "The order is already delivered. Confirm and enter a reason to receive it.",
                  "full_address": "SR10000001",
                  "status": "Successful",
                  "code": "order_delivered",
                  "confirmation_required": true
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.pickup-order.ref.post",
        "x-capability": "driver.delivery"
      }
    },
    "/app/v1/driver/orders/{orderId}/chat": {
      "get": {
        "tags": [
          "Order Chat"
        ],
        "summary": "Order chat thread (driver view)",
        "description": "Chat thread of one of the calling driver's assigned orders: only messages delivered to the driver. Orders not assigned to the caller answer 404. Requires the `driver_chat` switch of the option. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 5551
          },
          {
            "name": "since_id",
            "in": "query",
            "required": false,
            "description": "Only messages with an id greater than this",
            "schema": {
              "type": "integer"
            },
            "example": 0
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "feature_enabled": true,
                  "conversation": {
                    "id": 12,
                    "order_id": 5551,
                    "status": "open",
                    "locked": false,
                    "last_message_at": "2026-09-01 14:05:00",
                    "unread": {
                      "dispatcher": 0,
                      "driver": 1,
                      "customer": 0
                    },
                    "can_send": true,
                    "driver_chat": true,
                    "customer_chat": false,
                    "driver_to_customer": false,
                    "allow_attachments": true,
                    "quick_replies": [
                      "On my way",
                      "Running late"
                    ]
                  },
                  "order": {
                    "id": 5551,
                    "ref": "ORD-5551",
                    "tracking_number": "SR123456",
                    "status_id": 16,
                    "driver_id": 11,
                    "driver_alias": "Alex"
                  },
                  "messages": [
                    {
                      "id": 102,
                      "conversation_id": 12,
                      "sender_type": "dispatcher",
                      "sender_user_id": 700,
                      "sender_name": "Ops Team",
                      "body": "Please call the customer before arriving",
                      "attachment_url": null,
                      "delivered_to": [
                        "driver"
                      ],
                      "created_at": "2026-09-01 14:05:00",
                      "read_at_dispatcher": "2026-09-01 14:05:00",
                      "read_at_driver": null,
                      "read_at_customer": null
                    }
                  ],
                  "poll_interval": 15
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found, or order not assigned to the caller"
          },
          "409": {
            "description": "Feature disabled"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.chat.get",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrderChat",
        "operationId": "driverOrderChat"
      },
      "post": {
        "tags": [
          "Order Chat"
        ],
        "summary": "Send a driver message into an order chat",
        "description": "Posts a driver message into the thread of one of the caller's assigned orders. Reaches the dispatcher, and the customer too when `driver_to_customer` is on. Image as multipart `attachment` or `attachment_base64`. Throttled 60/min. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 5551
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "body": "On my way",
                "attachment_base64": null
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string"
                  },
                  "attachment": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message stored",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "feature_enabled": true,
                  "message": {
                    "id": 103,
                    "conversation_id": 12,
                    "sender_type": "driver",
                    "sender_user_id": 901,
                    "sender_name": "Alex",
                    "body": "On my way",
                    "attachment_url": null,
                    "delivered_to": [
                      "dispatcher"
                    ],
                    "created_at": "2026-09-01 14:06:00",
                    "read_at_dispatcher": null,
                    "read_at_driver": "2026-09-01 14:06:00",
                    "read_at_customer": null
                  },
                  "conversation": {
                    "id": 12,
                    "order_id": 5551,
                    "status": "open",
                    "locked": false,
                    "last_message_at": "2026-09-01 14:06:00",
                    "unread": {
                      "dispatcher": 1,
                      "driver": 0,
                      "customer": 0
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found, or order not assigned to the caller"
          },
          "409": {
            "description": "Feature disabled, or conversation locked"
          },
          "422": {
            "description": "Empty body without attachment, body too long, attachment refused"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.chat.post",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrderChatSend",
        "operationId": "driverOrderChatSend"
      }
    },
    "/app/v1/driver/orders/{orderId}/chat/read": {
      "post": {
        "tags": [
          "Order Chat"
        ],
        "summary": "Mark an order chat as read (driver)",
        "description": "Stamps read_at_driver on every message delivered to the driver and clears the driver unread counter. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 5551
          }
        ],
        "responses": {
          "200": {
            "description": "Marked read",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "feature_enabled": true,
                  "order_id": 5551,
                  "unread": 0
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found, or order not assigned to the caller"
          },
          "409": {
            "description": "Feature disabled"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.orders.orderId.chat.read.post",
        "x-capability": "driver.delivery",
        "operationId": "driverOrdersOrderIdChatReadPost"
      }
    },
    "/app/v1/driver/chat/unread": {
      "get": {
        "tags": [
          "Order Chat"
        ],
        "summary": "Driver unread chat counters",
        "description": "Per-order unread chat message counters for the calling driver's assigned orders. Answers 409 with `feature_enabled: false` while the option (or its `driver_chat` switch) is off. Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "example": {
                  "result": true,
                  "feature_enabled": true,
                  "items": [
                    {
                      "order_id": 5551,
                      "order_ref": "ORD-5551",
                      "unread": 1,
                      "last_message_at": "2026-09-01 14:05:00"
                    }
                  ],
                  "unread_total": 1
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Driver profile not found"
          },
          "409": {
            "description": "Feature disabled"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.chat.unread.get",
        "x-capability": "driver.delivery",
        "x-graphql": "driverOrderChatUnread",
        "operationId": "driverOrderChatUnread"
      }
    },
    "/app/v1/notifications/realtime": {
      "get": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Get foreground notification MQTT credentials",
        "description": "Returns short-lived MQTT-over-WebSocket credentials scoped to the authenticated app, Client assignment, customer and device. When realtime is unavailable, data.enabled is false and the app continues using API refresh. Each message carries v, event_id, type, category, entity_type, entity_id, deep_link and created_at, and since the customer app also title, body (the notification text) and alert (true when the user's push channel is on). Needs notifications.in_app on the token. Answered exactly as the internal route.",
        "operationId": "platformAppNotificationRealtime",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 191,
              "example": "ios-device-1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Realtime availability and short-lived credentials",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result",
                    "data"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "enabled"
                      ],
                      "properties": {
                        "enabled": {
                          "type": "boolean"
                        },
                        "mqtt_url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "client_id": {
                          "type": "string"
                        },
                        "username": {
                          "type": "string"
                        },
                        "password": {
                          "type": "string"
                        },
                        "topic": {
                          "type": "string"
                        },
                        "qos": {
                          "type": "integer",
                          "enum": [
                            1
                          ]
                        },
                        "contract_version": {
                          "type": "integer",
                          "enum": [
                            1
                          ]
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "enabled": true,
                    "mqtt_url": "wss://api.superroute.ca/mqtt",
                    "client_id": "pa-a1b2c3d4e5f6g7h8i9j0",
                    "username": "app-1-assignment-10-user-100-device-a1b2c3d4e5f6g7h8",
                    "password": "short-lived-jwt",
                    "topic": "sr/apps/1/assignments/10/users/100/notifications",
                    "qos": 1,
                    "contract_version": 1,
                    "expires_at": "2026-07-25T18:00:00Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or app or client access is not allowed"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.notifications.realtime",
        "x-graphql": "platformAppNotificationRealtime",
        "x-capability": "notifications.in_app"
      }
    },
    "/app/v1/devices": {
      "post": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Register an app push device",
        "description": "Stores an encrypted FCM token scoped to the user and App-Client assignment. Additive: `live_pickup_enabled` and `live_activity_start_token` (see request fields); the device in the response carries `live_pickup_enabled`. While a customer's locker pickup can be collected, a device with the switch on shows its code on the lock screen: Android receives high-priority data messages {type: pickup_live, action: show|hide, delivery_id, code, title, body, expires_at, deep_link}; iOS gets a Live Activity (attributes type PickupActivityAttributes {deliveryId, locationName}, content state {code, remaining, expiresAt (unix seconds), status ready|ended, title, subtitle (ready to show, in the device's preferred_locale)}) started, updated and ended by push. Needs notifications.push on the token. Pushes go out with the APNs key and FCM service account uploaded for the app; Live Activity and lock-screen pickup fields are ignored. Answered exactly as the internal route.",
        "operationId": "platformAppRegisterDevice",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "push_token",
                  "device_id",
                  "device_platform"
                ],
                "properties": {
                  "push_token": {
                    "type": "string",
                    "maxLength": 4096
                  },
                  "device_id": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "device_platform": {
                    "type": "string",
                    "enum": [
                      "ios",
                      "android"
                    ]
                  },
                  "preferred_locale": {
                    "type": "string"
                  },
                  "app_version": {
                    "type": "string"
                  },
                  "live_pickup_enabled": {
                    "type": "boolean",
                    "description": "Additive. The customer's \"pickup code on the lock screen\" switch; omitted keeps the device's value (on by default)."
                  },
                  "live_activity_start_token": {
                    "type": "string",
                    "description": "Additive, iOS 17.2+. The Live Activity push-to-start token the server starts a pickup-code Live Activity with; an empty string clears it."
                  }
                }
              },
              "example": {
                "push_token": "fcm-token",
                "device_id": "device-uuid",
                "device_platform": "android",
                "preferred_locale": "en",
                "app_version": "1.0.0"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Push device registered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or app or client access is not allowed"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.devices.register",
        "x-graphql": "platformAppRegisterDevice",
        "x-capability": "notifications.push"
      }
    },
    "/app/v1/devices/{deviceId}": {
      "delete": {
        "tags": [
          "Platform Apps"
        ],
        "summary": "Revoke an app push device",
        "operationId": "platformAppRevokeDevice",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "parameters": [
          {
            "name": "deviceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Push device revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or app or client access is not allowed"
          },
          "422": {
            "description": "Invalid request"
          }
        },
        "x-route-name": "openapp.devices.revoke",
        "x-graphql": "platformAppRevokeDevice",
        "x-capability": "notifications.push",
        "description": "Needs notifications.push on the token. Pushes go out with the APNs key and FCM service account uploaded for the app; Live Activity and lock-screen pickup fields are ignored. Answered exactly as the internal route."
      }
    },
    "/app/v1/sessions": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "List the person's sign-ins to this app",
        "operationId": "partnerAppSessions",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "One entry per sign-in (token family) of this app at this client, newest first; `current` marks the calling token's. Our own apps' sessions are never listed.",
        "responses": {
          "200": {
            "description": "Sign-ins",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "result"
                  ],
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Token family id"
                              },
                              "device_id": {
                                "type": "string",
                                "nullable": true
                              },
                              "auth_method": {
                                "type": "string"
                              },
                              "current": {
                                "type": "boolean"
                              },
                              "active": {
                                "type": "boolean"
                              },
                              "last_seen_at": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "created_at": {
                                "type": "string",
                                "format": "date-time"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": "01JBX8V6Q4K2N7R9T3W5Y8Z1A2",
                        "device_id": "ios-7f3a",
                        "auth_method": "password",
                        "current": true,
                        "active": true,
                        "last_seen_at": "2026-10-28T14:05:00-04:00",
                        "created_at": "2026-10-20T09:12:00-04:00"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          }
        },
        "x-route-name": "openapp.sessions.index",
        "x-graphql": "partnerAppSessions"
      }
    },
    "/app/v1/sessions/{sessionId}": {
      "delete": {
        "tags": [
          "Account"
        ],
        "summary": "End one sign-in",
        "operationId": "partnerAppRevokeSession",
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "description": "Revokes every token of the sign-in. A sign-in of another app or person answers 404.",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9A-Za-z]{26}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ended",
            "content": {
              "application/json": {
                "example": {
                  "result": true
                }
              }
            }
          },
          "401": {
            "description": "invalid_token"
          },
          "404": {
            "description": "Session not found",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "message": "Session not found."
                }
              }
            }
          }
        },
        "x-route-name": "openapp.sessions.revoke",
        "x-graphql": "partnerAppRevokeSession"
      }
    },
    "/app/v1/clients/{clientCode}/driver/register": {
      "post": {
        "summary": "Sign up a driver",
        "description": "Driver apps only, with the restricted app key (X-App-Key). The driver joins the client named by clientCode; a business_id in the body is ignored. The client must have driver.registration switched on for the app, and its own driver self-registration rules apply (off: 401; with review: the driver waits for approval). A developer signing up drivers for its own business needs nothing more; for any other client the developer must hold app.driver_registration, granted by a platform admin on application (403 otherwise).",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "tags": [
          "Driver"
        ],
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The client's public code"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "alias": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "telephone": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string",
                    "nullable": true
                  },
                  "address_2": {
                    "type": "string",
                    "nullable": true
                  },
                  "city": {
                    "type": "string",
                    "nullable": true
                  },
                  "province": {
                    "type": "string",
                    "nullable": true
                  },
                  "country": {
                    "type": "string",
                    "nullable": true
                  },
                  "postcode": {
                    "type": "string",
                    "nullable": true
                  },
                  "language": {
                    "type": "string"
                  },
                  "capacity": {
                    "type": "integer",
                    "nullable": true
                  },
                  "territory_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "start_location_id": {
                    "type": "integer",
                    "nullable": true
                  },
                  "end_location_id": {
                    "type": "integer",
                    "nullable": true
                  }
                },
                "required": [
                  "alias",
                  "name",
                  "password",
                  "email",
                  "telephone",
                  "language"
                ]
              },
              "example": {
                "alias": "driver01",
                "name": "John",
                "password": "12345678",
                "email": "join3@gmail.com",
                "telephone": "5555555555",
                "address": "demo",
                "address_2": "demo",
                "city": "demo",
                "province": "demo",
                "country": "CA",
                "postcode": "H0H0H0",
                "language": "en",
                "capacity": null,
                "territory_id": null,
                "start_location_id": null,
                "end_location_id": null
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful registration",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": "integer"
                    },
                    "business_id": {
                      "type": "string"
                    },
                    "Email": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "language": {
                      "type": "string"
                    },
                    "alias": {
                      "type": "string"
                    },
                    "telephone": {
                      "type": "string"
                    },
                    "capacity": {
                      "type": "integer",
                      "nullable": true
                    },
                    "start_location_id": {
                      "type": "integer",
                      "nullable": true
                    },
                    "end_location_id": {
                      "type": "integer",
                      "nullable": true
                    },
                    "territory_id": {
                      "type": "integer",
                      "nullable": true
                    },
                    "skills": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "example": {
                  "result": true,
                  "id": 790,
                  "business_id": "1704",
                  "Email": "join34@gmail.com",
                  "name": "John",
                  "status": 0,
                  "language": "en",
                  "alias": "driver01",
                  "telephone": "5555555555",
                  "capacity": null,
                  "start_location_id": null,
                  "end_location_id": null,
                  "territory_id": null,
                  "skills": []
                }
              }
            }
          },
          "429": {
            "description": "Too many registration attempts from this IP (limit: 10 per minute). Retry after the delay indicated by the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Too Many Attempts."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Driver sign-up is not switched on, or the app may sign up drivers for its own business only",
            "content": {
              "application/json": {
                "example": {
                  "message": [
                    "This app may sign up drivers for its own business only."
                  ]
                }
              }
            }
          }
        },
        "operationId": "partnerAppDriverRegister",
        "x-route-name": "openapp.driver.register",
        "x-graphql": "partnerAppDriverRegister"
      }
    },
    "/app/v1/driver/return-reasons/{order_id?}": {
      "get": {
        "tags": [
          "Driver"
        ],
        "summary": "Reasons for a failed stop",
        "description": "The reasons a driver may give when a stop fails (sent as return_reason_id to update-deliver), each in the driver's language, in the business's own order. With order_id only the reasons valid for that order's direction (delivery or pickup). Driver apps only; needs driver.delivery on the token. Answered exactly as the internal driver route (/v1/returnreasons/{order_id?}).",
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Narrows the reasons to the order's direction"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": 3,
                    "reason": "Recipient not home",
                    "business_id": 2,
                    "status": 1,
                    "sort_number": 10,
                    "receive_status": 0,
                    "visible_to_public": 1,
                    "for_delivery": 1,
                    "for_pickup": 0,
                    "created_at": "2026-01-10 09:00:00"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "The order is not the business's, or is a label service order"
          },
          "401": {
            "description": "invalid_token"
          },
          "403": {
            "description": "insufficient_scope, or not a driver app (wrong_app_audience)"
          }
        },
        "security": [
          {
            "partnerAppToken": []
          }
        ],
        "x-route-name": "openapp.driver.return-reasons.get",
        "x-capability": "driver.delivery",
        "x-graphql": "returnreasons",
        "operationId": "driverReturnReasons"
      }
    },
    "/app/v1/clients/{clientCode}/swidget": {
      "get": {
        "x-route-name": "openapp.swidget.config",
        "x-graphql": "partnerAppSwidget",
        "tags": [
          "sWidget"
        ],
        "summary": "sWidget configuration",
        "description": "The configuration of the sWidget widget the app key belongs to (docs/SWIDGET-DESIGN.md): type (tracking, quote, order, pickup_point), its options, the branding, the language and `country` (the client's own country, ISO 3166-1 alpha-2, added in runtime 0.2.0). An order widget names its mode: `guest` (with the client's guest shipping offer) or `sign_in` (with the redirect URI of the sign-in page). A key that belongs to no widget answers 404 `not_a_widget`. A key that belongs to an sWidget widget (docs/SWIDGET-DESIGN.md) works only from the widget's own website origins (an `Origin` header is required), for the widget's own client and for the calls of its type; other calls answer 403 `widget_call_not_allowed`, other origins 403 `origin_not_allowed`.",
        "operationId": "partnerAppSwidget",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          }
        ],
        "responses": {
          "200": {
            "description": "The widget's configuration",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "widget": {
                      "id": "k2m9q7x4b1c8",
                      "type": "order",
                      "name": "Ship with us",
                      "locale": null,
                      "options": {
                        "order_mode": "sign_in",
                        "service_code": "STD",
                        "sign_in": {
                          "redirect_uri": "https://open.superroute.ca/app/oauth/swidget/callback"
                        }
                      }
                    },
                    "branding": {
                      "display_name": "Acme Delivery",
                      "primary_color": "#E02020",
                      "logo_url": "https://acme.example/logo.png"
                    },
                    "country": "CA",
                    "app_code": "p_swidget",
                    "client_code": "k3m9q2"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid app key"
          },
          "403": {
            "description": "Origin, call or capability refused"
          },
          "429": {
            "description": "Too many requests (the route's own limit, or a widget key's limits: `too_many_requests`); `Retry-After` says how many seconds to wait"
          },
          "404": {
            "description": "Not available for this service provider"
          }
        }
      }
    },
    "/app/v1/clients/{clientCode}/swidgets/{widgetId}": {
      "get": {
        "x-route-name": "openapp.swidgets.show",
        "x-graphql": "platformAppSwidget",
        "tags": [
          "sWidget"
        ],
        "summary": "Load a widget by its id",
        "description": "A widget the Client configured in the back office, loaded by its id from an app the Client ticked on it (docs/SWIDGET-SDK-DESIGN.md WS7, WS8). The answer has the shape of the sWidget configuration (`widget`, `branding`, `country`, `app_code`, `client_code`) plus `config_version` (1), `channel` (`app`) and `unavailable`: the capabilities this app's assignment lacks for the widget's kind (WS9; every later call is an ordinary call of the app under its own capabilities). Branding is the widget's own, else this app's branding at the Client, else the Client's name. A sign-in order widget carries no redirect URI: in an app, signing in is the app's own sign-in. Errors: 404 `widget_not_found` (unknown id or another Client's widget), 403 `widget_not_enabled_for_app` (this app is not ticked on the widget), 410 `widget_revoked`. The app's own key (`X-App-Key`); a widget's key is refused here (403 `widget_call_not_allowed`).",
        "operationId": "platformAppSwidgetShow",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "widgetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9]{8,24}$"
            },
            "description": "The widget's public id."
          }
        ],
        "responses": {
          "200": {
            "description": "The widget's configuration",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "widget": {
                      "id": "k2m9q7x4b1c8",
                      "type": "tracking",
                      "name": "Track a parcel",
                      "locale": null,
                      "options": {}
                    },
                    "branding": {
                      "display_name": "Acme Delivery",
                      "primary_color": "#E02020",
                      "logo_url": null
                    },
                    "country": "CA",
                    "app_code": "mibox",
                    "client_code": "k3m9q2",
                    "config_version": 1,
                    "channel": "app",
                    "unavailable": []
                  }
                }
              }
            }
          },
          "403": {
            "description": "widget_not_enabled_for_app",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "error": "widget_not_enabled_for_app",
                  "error_description": "This widget is not enabled for this app."
                }
              }
            }
          },
          "404": {
            "description": "widget_not_found",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "error": "widget_not_found",
                  "error_description": "No such widget at this service provider."
                }
              }
            }
          },
          "410": {
            "description": "widget_revoked",
            "content": {
              "application/json": {
                "example": {
                  "result": false,
                  "error": "widget_revoked",
                  "error_description": "This widget was revoked."
                }
              }
            }
          }
        }
      }
    },
    "/app/v1/clients/{clientCode}/guest/quotes/schema": {
      "get": {
        "x-route-name": "openapp.guest.quotes.schema",
        "x-graphql": "partnerAppGuestQuoteSchema",
        "x-capability": "quotes.public",
        "tags": [
          "Platform Apps"
        ],
        "summary": "Quote form (guest)",
        "description": "The quote form a client offers to a visitor who has not signed in: its lines, their fields, origins and units. Same answer as platformAppPublicQuoteSchema and the /quotes page. Needs quotes.public at the assignment and public quotes switched on by the client; otherwise 404 APP_CONTEXT_NOT_FOUND. A key that belongs to an sWidget widget (docs/SWIDGET-DESIGN.md) works only from the widget's own website origins (an `Origin` header is required), for the widget's own client and for the calls of its type; other calls answer 403 `widget_call_not_allowed`, other origins 403 `origin_not_allowed`.",
        "operationId": "partnerAppGuestQuoteSchema",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The quote form",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "schema": {
                    "business_name": "Acme Delivery",
                    "currency": "CAD",
                    "valid_days": 7,
                    "country": "CA",
                    "units": {
                      "weight": {
                        "default": 2,
                        "options": {
                          "1": "weight_g",
                          "2": "weight_kg",
                          "3": "weight_oz",
                          "4": "weight_lb"
                        }
                      },
                      "dimension": {
                        "default": 2,
                        "options": {
                          "1": "dimension_mm",
                          "2": "dimension_cm",
                          "3": "dimension_m",
                          "4": "dimension_inch"
                        }
                      }
                    },
                    "lines": {
                      "delivery": {
                        "line": "delivery",
                        "max_package_count": 5,
                        "origins": [],
                        "custom_origin": true
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid app key"
          },
          "403": {
            "description": "Origin, call or capability refused"
          },
          "429": {
            "description": "Too many requests (the route's own limit, or a widget key's limits: `too_many_requests`); `Retry-After` says how many seconds to wait"
          },
          "404": {
            "description": "Not available for this service provider"
          }
        }
      }
    },
    "/app/v1/clients/{clientCode}/guest/quotes/{line}": {
      "post": {
        "x-route-name": "openapp.guest.quotes.quote",
        "x-graphql": "partnerAppGuestQuote",
        "x-capability": "quotes.public",
        "tags": [
          "Platform Apps"
        ],
        "summary": "Quote one line (guest)",
        "description": "A quote on one line for a visitor who has not signed in, recorded as on the /quotes page (PublicQuoteService). The body is the line's input (postcodes, packages with weight / dimensions and units, a shipping service or label method). Carrier lines are limited to six quotes per minute per visitor. Answers `result: false` with `not_covered_reason` when the shipment cannot be priced, 422 with `errors` on bad input. A key that belongs to an sWidget widget (docs/SWIDGET-DESIGN.md) works only from the widget's own website origins (an `Origin` header is required), for the widget's own client and for the calls of its type; other calls answer 403 `widget_call_not_allowed`, other origins 403 `origin_not_allowed`.",
        "operationId": "partnerAppGuestQuote",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "line",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "delivery",
                "pickup",
                "p2p",
                "shipping",
                "label",
                "express",
                "moving",
                "storage",
                "property"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              },
              "example": {
                "to_postcode": "M5V 2T6",
                "to_country": "CA",
                "weight_unit": 2,
                "dimension_unit": 2,
                "packages": [
                  {
                    "weight": 2,
                    "length": 30,
                    "width": 20,
                    "height": 10,
                    "qty": 1
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The quote",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "quote": {
                    "covered": true,
                    "line": "delivery",
                    "currency": "CAD",
                    "pre_tax": 12.5,
                    "tax": 1.63,
                    "total": 14.13,
                    "breakdown": [],
                    "not_covered_reason": null,
                    "token": "q8w2…",
                    "valid_until": "2026-11-05T10:00:00-05:00"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid app key"
          },
          "403": {
            "description": "Origin, call or capability refused"
          },
          "429": {
            "description": "Too many requests (the route's own limit, or a widget key's limits: `too_many_requests`); `Retry-After` says how many seconds to wait"
          },
          "404": {
            "description": "Not available for this service provider"
          }
        }
      }
    },
    "/app/v1/clients/{clientCode}/guest/pickup-points": {
      "get": {
        "x-route-name": "openapp.guest.pickup-points",
        "x-graphql": "partnerAppGuestPickupPoints",
        "tags": [
          "Platform Apps"
        ],
        "summary": "Pickup points (guest)",
        "description": "The client's smart locker locations and active pickup point counters a visitor may choose, in the answer shape of platformAppLockerLocations, nearest first when a position is given, else by name. Ids are prefixed by kind (`L` locker location, `C` counter); `location_id` is the address id. Nothing about a person is answered. Read only. An sWidget pickup point widget lists only the kinds it was set up with. A key that belongs to an sWidget widget (docs/SWIDGET-DESIGN.md) works only from the widget's own website origins (an `Origin` header is required), for the widget's own client and for the calls of its type; other calls answer 403 `widget_call_not_allowed`, other origins 403 `origin_not_allowed`.",
        "operationId": "partnerAppGuestPickupPoints",
        "security": [
          {
            "partnerAppKey": []
          }
        ],
        "parameters": [
          {
            "name": "clientCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service provider's public client code for this app."
          },
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "pickup",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "return",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "available",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pickup points",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "example": {
                  "result": true,
                  "data": {
                    "items": [
                      {
                        "id": "L12",
                        "kind": "locker",
                        "location_id": 12,
                        "name": "Union Station lockers",
                        "address": "65 Front St W",
                        "city": "Toronto",
                        "province": "ON",
                        "postcode": "M5J 1E6",
                        "country": "CA",
                        "latitude": 43.6453,
                        "longitude": -79.3806,
                        "distance_km": 0.8,
                        "status": "online",
                        "services": {
                          "pickup": true,
                          "return": true,
                          "dropoff": true
                        }
                      },
                      {
                        "id": "C40",
                        "kind": "counter",
                        "location_id": 40,
                        "name": "Corner shop",
                        "address": "12 King St W",
                        "city": "Toronto",
                        "province": "ON",
                        "postcode": "M5H 1A1",
                        "country": "CA",
                        "latitude": 43.6487,
                        "longitude": -79.3787,
                        "distance_km": 1.1,
                        "status": "online",
                        "services": {
                          "pickup": true,
                          "return": false,
                          "dropoff": false
                        },
                        "has_room": true
                      }
                    ],
                    "pagination": {
                      "current_page": 1,
                      "per_page": 20,
                      "total": 2,
                      "last_page": 1,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid app key"
          },
          "403": {
            "description": "Origin, call or capability refused"
          },
          "429": {
            "description": "Too many requests (the route's own limit, or a widget key's limits: `too_many_requests`); `Retry-After` says how many seconds to wait"
          },
          "404": {
            "description": "Not available for this service provider"
          }
        }
      }
    },
    "/app/oauth/swidget/callback": {
      "get": {
        "x-route-name": "openapp.oauth.swidget_callback",
        "tags": [
          "OAuth"
        ],
        "summary": "sWidget sign-in return page",
        "description": "The redirect URI of the sWidget app (docs/SWIDGET-DESIGN.md W7). `state` names the widget and the page that opened the sign-in (base64url JSON `{w, o, n}`); the page posts `{type: 'swidget-sign-in', state, code}` (or `error`) to that page with postMessage, only when its origin is one of the widget's own, and closes. Anything else shows an error page and posts nothing.",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 500
            }
          },
          {
            "name": "error",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ui_locales",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An HTML page that hands the code to the widget"
          },
          "400": {
            "description": "An HTML error page: unknown widget or an origin the widget does not have"
          }
        }
      }
    }
  }
}
