{
 "openapi": "3.1.0",
 "info": {
  "title": "Mock Service API (staging)",
  "version": "1.12.0",
  "description": "Staging-only trigger operations that simulate parcel and locker events.\nFor the first steps, read the [Testing guide](#tag/Testing-guide).\n\n> **Staging only**\n>\n> Base URL: `https://api.staging.glsnxt.com/ooh-mock-service/v1`.\n> Authenticate with your regular carrier staging API key in the `X-API-Key` header.\n> You do not need a separate mock-service key.\n\nRequest bodies use `snake_case` field names.\nA booking uses the platform `lockerUid`. A trigger request uses the provider-side `provider_locker_id`.\nFor a test locker the two values can be equal, but this is not always true. Read `provider_locker_id` from the platform (see the Testing guide, section 2.1).\n\n> **A `200` response is not a confirmation**\n>\n> The mock answers `200` when it accepts the request, before it sends the event.\n> The `message` text, for example `Last Mile event triggered successfully`, has the same meaning.\n> The platform processes the event a few seconds later. If the platform rejects or drops the event, you get no error from the mock.\n> Always check the result in your webhooks or with `GET /parcels` (Testing guide, section 2.2).\n\nAlways send your own carrier name in `carrier_name`. With a different carrier name, the mock returns `200`, but the platform drops the event."
 },
 "servers": [
  {
   "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
   "description": "Staging"
  }
 ],
 "security": [
  {
   "ApiKeyAuth": []
  }
 ],
 "tags": [
  {
   "name": "Mock Service API",
   "description": "Staging-only trigger operations that simulate parcel and locker events.\nFor the first steps, read the [Testing guide](#tag/Testing-guide).\n\n> **Staging only**\n>\n> Base URL: `https://api.staging.glsnxt.com/ooh-mock-service/v1`.\n> Authenticate with your regular carrier staging API key in the `X-API-Key` header.\n> You do not need a separate mock-service key.\n\nRequest bodies use `snake_case` field names.\nA booking uses the platform `lockerUid`. A trigger request uses the provider-side `provider_locker_id`.\nFor a test locker the two values can be equal, but this is not always true. Read `provider_locker_id` from the platform (see the Testing guide, section 2.1).\n\n> **A `200` response is not a confirmation**\n>\n> The mock answers `200` when it accepts the request, before it sends the event.\n> The `message` text, for example `Last Mile event triggered successfully`, has the same meaning.\n> The platform processes the event a few seconds later. If the platform rejects or drops the event, you get no error from the mock.\n> Always check the result in your webhooks or with `GET /parcels` (Testing guide, section 2.2).\n\nAlways send your own carrier name in `carrier_name`. With a different carrier name, the mock returns `200`, but the platform drops the event."
  }
 ],
 "paths": {
  "/parcel/first-mile/event": {
   "post": {
    "tags": [
     "Mock Service API"
    ],
    "summary": "Trigger first-mile event",
    "description": "Triggers one first-mile or return parcel event for the selected provider and carrier.\nA `200` response means only that the mock accepted the request. Check the new status in your webhooks or with `GET /parcels`.",
    "operationId": "triggerFirstMileEvent",
    "servers": [
     {
      "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
      "description": "Staging mock service"
     }
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "x-internal": true,
        "required": [
         "parcel_id",
         "provider_locker_id",
         "provider_name",
         "carrier_name",
         "shipment_type",
         "event_type"
        ],
        "properties": {
         "parcel_id": {
          "type": "string",
          "description": "Your parcel ID (`carrierParcelId`). For a booked parcel, use the ID from the booking. For a new test parcel, use a new ID that starts with `000`.",
          "example": "000123456789"
         },
         "provider_locker_id": {
          "type": "string",
          "description": "The locker ID on the provider side. This is not always the platform `lockerUid`. Read it from `provider.lockerUid` in `GET /lockers/by-uid`, or from `providerLockerId` in `GET /parcels`.",
          "example": "99663306"
         },
         "event_type": {
          "x-internal": true,
          "type": "string",
          "description": "Event to trigger.",
          "enum": [
           "BOOKING_CREATED",
           "COURIER_COLLECTED",
           "CONSIGNEE_DELIVERED"
          ],
          "example": "CONSIGNEE_DELIVERED"
         },
         "carrier_name": {
          "x-internal": true,
          "type": "string",
          "description": "Your own carrier name: the carrier that owns your `X-API-Key`, the parcel and the locker. The mock does not compare this value with your API key. With a different carrier name, the mock returns `200`, but the platform drops the event and the parcel status does not change.",
          "enum": [
           "GLS_NXT",
           "GLS_DE",
           "GLS_AT",
           "DPD_DE",
           "GLS_ES",
           "GLS_IT",
           "GLS_PT",
           "GLS_DK",
           "GLS_FR",
           "RMG_UK",
           "GLS_SI",
           "KLEINANZEIGEN_DE"
          ],
          "example": "GLS_DE"
         },
         "provider_name": {
          "x-internal": true,
          "type": "string",
          "description": "The provider of the test locker. Read it from `provider.name` in `GET /lockers/by-uid`, or from `providerName` in `GET /parcels`.",
          "enum": [
           "KEBA",
           "MYFLEXBOX_DE",
           "MYFLEXBOX_AT",
           "TAMBURI_AT",
           "QUADIENT",
           "BLOQ",
           "CAINIAO_FR"
          ],
          "example": "KEBA"
         },
         "shipment_type": {
          "x-internal": true,
          "type": "string",
          "description": "FIRST_MILE or RETURN.",
          "enum": [
           "FIRST_MILE",
           "RETURN"
          ],
          "example": "FIRST_MILE"
         },
         "labelless": {
          "type": "boolean",
          "description": "Optional. Set true only for confirmed label-less combinations.",
          "example": false
         }
        }
       },
       "example": {
        "parcel_id": "<YOUR_CARRIER_PARCEL_ID>",
        "provider_locker_id": "<PROVIDER_LOCKER_ID>",
        "provider_name": "BLOQ",
        "carrier_name": "GLS_DE",
        "shipment_type": "FIRST_MILE",
        "event_type": "CONSIGNEE_DELIVERED"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Request accepted. This does not confirm that the platform applied the event: the mock sends the event a few seconds later. Check the result in your webhooks or with `GET /parcels`.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "x-internal": true,
         "required": [
          "message"
         ],
         "properties": {
          "message": {
           "type": "string",
           "example": "First Mile event triggered successfully"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/mock_trigger_400"
     },
     "401": {
      "$ref": "#/components/responses/gateway_401"
     }
    }
   }
  },
  "/parcel/first-mile/sequence": {
   "post": {
    "tags": [
     "Mock Service API"
    ],
    "summary": "Trigger first-mile sequence",
    "description": "Triggers a full first-mile or return event sequence.\nDo not send `event_type`. The mock selects the sequence from `provider_name`, `shipment_type` and `labelless`.\nThe events arrive through your webhooks after the `200` response.",
    "operationId": "triggerFirstMileSequence",
    "servers": [
     {
      "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
      "description": "Staging mock service"
     }
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "x-internal": true,
        "required": [
         "parcel_id",
         "provider_locker_id",
         "provider_name",
         "carrier_name",
         "shipment_type"
        ],
        "properties": {
         "parcel_id": {
          "type": "string",
          "description": "Your parcel ID (`carrierParcelId`). For a booked parcel, use the ID from the booking. For a new test parcel, use a new ID that starts with `000`.",
          "example": "000123456789"
         },
         "provider_locker_id": {
          "type": "string",
          "description": "The locker ID on the provider side. This is not always the platform `lockerUid`. Read it from `provider.lockerUid` in `GET /lockers/by-uid`, or from `providerLockerId` in `GET /parcels`.",
          "example": "99663306"
         },
         "carrier_name": {
          "x-internal": true,
          "type": "string",
          "description": "Your own carrier name: the carrier that owns your `X-API-Key`, the parcel and the locker. The mock does not compare this value with your API key. With a different carrier name, the mock returns `200`, but the platform drops the event and the parcel status does not change.",
          "enum": [
           "GLS_NXT",
           "GLS_DE",
           "GLS_AT",
           "DPD_DE",
           "GLS_ES",
           "GLS_IT",
           "GLS_PT",
           "GLS_DK",
           "GLS_FR",
           "RMG_UK",
           "GLS_SI",
           "KLEINANZEIGEN_DE"
          ],
          "example": "GLS_DE"
         },
         "provider_name": {
          "x-internal": true,
          "type": "string",
          "description": "The provider of the test locker. Read it from `provider.name` in `GET /lockers/by-uid`, or from `providerName` in `GET /parcels`.",
          "enum": [
           "KEBA",
           "MYFLEXBOX_DE",
           "MYFLEXBOX_AT",
           "TAMBURI_AT",
           "QUADIENT",
           "BLOQ",
           "CAINIAO_FR"
          ],
          "example": "KEBA"
         },
         "shipment_type": {
          "x-internal": true,
          "type": "string",
          "description": "FIRST_MILE or RETURN.",
          "enum": [
           "FIRST_MILE",
           "RETURN"
          ],
          "example": "FIRST_MILE"
         },
         "labelless": {
          "type": "boolean",
          "description": "Optional. Set true only for confirmed label-less combinations.",
          "example": false
         }
        }
       },
       "example": {
        "parcel_id": "<YOUR_CARRIER_PARCEL_ID>",
        "provider_locker_id": "<PROVIDER_LOCKER_ID>",
        "provider_name": "BLOQ",
        "carrier_name": "GLS_DE",
        "shipment_type": "FIRST_MILE",
        "labelless": false
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Request accepted. This does not confirm that the platform applied the events: the mock sends them one after another, starting a few seconds later. Check the result in your webhooks or with `GET /parcels`.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "x-internal": true,
         "required": [
          "message"
         ],
         "properties": {
          "message": {
           "type": "string",
           "example": "First Mile event sequence triggered successfully"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/mock_trigger_400"
     },
     "401": {
      "$ref": "#/components/responses/gateway_401"
     }
    }
   }
  },
  "/parcel/last-mile/event": {
   "post": {
    "tags": [
     "Mock Service API"
    ],
    "summary": "Trigger last-mile event",
    "description": "Triggers one last-mile parcel event for the selected provider and carrier.\nFor a parcel that you booked through `POST /parcels/data`, send the same parcel ID, your own carrier name, and the provider and provider locker ID of the booking.\nFor a new `parcel_id` without a booking, send `COURIER_DELIVERED` first. The platform creates the shipment and sets this status in one step.\nIf the first event for a new `parcel_id` is a different event, the platform ignores it.\nAfter `COURIER_DELIVERED`, send the next statuses for the same parcel.\nA `200` response means only that the mock accepted the request. Check the new status in your webhooks or with `GET /parcels`.",
    "operationId": "triggerLastMileEvent",
    "servers": [
     {
      "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
      "description": "Staging mock service"
     }
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "x-internal": true,
        "required": [
         "parcel_id",
         "provider_locker_id",
         "provider_name",
         "carrier_name",
         "shipment_type",
         "event_type"
        ],
        "properties": {
         "parcel_id": {
          "type": "string",
          "description": "Your parcel ID (`carrierParcelId`). For a booked parcel, use the ID from the booking. For a new test parcel, use a new ID that starts with `000`.",
          "example": "000123456789"
         },
         "provider_locker_id": {
          "type": "string",
          "description": "The locker ID on the provider side. This is not always the platform `lockerUid`. Read it from `provider.lockerUid` in `GET /lockers/by-uid`, or from `providerLockerId` in `GET /parcels`.",
          "example": "99663306"
         },
         "event_type": {
          "x-internal": true,
          "type": "string",
          "description": "Event to trigger.",
          "enum": [
           "COURIER_DELIVERED",
           "CONSIGNEE_COLLECTED",
           "CONSIGNEE_COLLECTION_EXPIRED",
           "BOOKING_CANCELLED",
           "COURIER_COLLECTED_EXPIRED",
           "COURIER_DELIVERY_ERROR"
          ],
          "example": "COURIER_DELIVERED"
         },
         "carrier_name": {
          "x-internal": true,
          "type": "string",
          "description": "Your own carrier name: the carrier that owns your `X-API-Key`, the parcel and the locker. The mock does not compare this value with your API key. With a different carrier name, the mock returns `200`, but the platform drops the event and the parcel status does not change.",
          "enum": [
           "GLS_NXT",
           "GLS_DE",
           "GLS_AT",
           "DPD_DE",
           "GLS_ES",
           "GLS_IT",
           "GLS_PT",
           "GLS_DK",
           "GLS_FR",
           "RMG_UK",
           "GLS_SI",
           "KLEINANZEIGEN_DE"
          ],
          "example": "GLS_DE"
         },
         "provider_name": {
          "x-internal": true,
          "type": "string",
          "description": "The provider of the test locker. Read it from `provider.name` in `GET /lockers/by-uid`, or from `providerName` in `GET /parcels`.",
          "enum": [
           "KEBA",
           "MYFLEXBOX_DE",
           "MYFLEXBOX_AT",
           "TAMBURI_AT",
           "LOCKY_PT",
           "QUADIENT",
           "BLOQ",
           "AMAZON_DE",
           "CAINIAO_FR"
          ],
          "example": "KEBA"
         },
         "shipment_type": {
          "x-internal": true,
          "type": "string",
          "description": "LAST_MILE or ALTERNATIVE_DELIVERY.",
          "enum": [
           "LAST_MILE",
           "ALTERNATIVE_DELIVERY"
          ],
          "example": "LAST_MILE"
         }
        }
       },
       "example": {
        "parcel_id": "<YOUR_CARRIER_PARCEL_ID>",
        "provider_locker_id": "<PROVIDER_LOCKER_ID>",
        "provider_name": "BLOQ",
        "carrier_name": "GLS_DE",
        "shipment_type": "LAST_MILE",
        "event_type": "COURIER_DELIVERED"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Request accepted. This does not confirm that the platform applied the event: the mock sends the event a few seconds later. Check the result in your webhooks or with `GET /parcels`.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "x-internal": true,
         "required": [
          "message"
         ],
         "properties": {
          "message": {
           "type": "string",
           "example": "Last Mile event triggered successfully"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/mock_trigger_400"
     },
     "401": {
      "$ref": "#/components/responses/gateway_401"
     }
    }
   }
  },
  "/locker/event": {
   "post": {
    "tags": [
     "Mock Service API"
    ],
    "summary": "Trigger locker event",
    "description": "Triggers a locker status event for the specified provider.\nA `200` response means only that the mock accepted the request.\nFor AMAZON_DE and CAINIAO_FR, include `provider_payload`.\nGLS/NXT supplies the required payload.\nOther providers do not need `provider_payload`.",
    "operationId": "triggerLockerEvent",
    "servers": [
     {
      "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
      "description": "Staging mock service"
     }
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "x-internal": true,
        "required": [
         "provider_locker_id",
         "provider_name",
         "carrier_name",
         "locker_status"
        ],
        "properties": {
         "provider_locker_id": {
          "type": "string",
          "description": "The locker ID on the provider side. This is not always the platform `lockerUid`. Read it from `provider.lockerUid` in `GET /lockers/by-uid`, or from `providerLockerId` in `GET /parcels`.",
          "example": "99663306"
         },
         "provider_name": {
          "x-internal": true,
          "type": "string",
          "description": "The provider of the test locker. Read it from `provider.name` in `GET /lockers/by-uid`, or from `providerName` in `GET /parcels`.",
          "enum": [
           "BLOQ",
           "KEBA",
           "MYFLEXBOX_DE",
           "MYFLEXBOX_AT",
           "TAMBURI_AT",
           "LOCKY_PT",
           "AMAZON_DE",
           "CAINIAO_FR"
          ],
          "example": "KEBA"
         },
         "locker_status": {
          "x-internal": true,
          "type": "string",
          "description": "Target locker status.",
          "enum": [
           "ACTIVE",
           "INACTIVE"
          ],
          "example": "ACTIVE"
         },
         "carrier_name": {
          "x-internal": true,
          "type": "string",
          "description": "Your own carrier name: the carrier that owns your `X-API-Key` and the locker. The mock does not compare this value with your API key. Send your own carrier name, so that the platform applies the event to your locker.",
          "enum": [
           "GLS_NXT",
           "GLS_DE",
           "GLS_AT",
           "DPD_DE",
           "GLS_ES",
           "GLS_IT",
           "GLS_PT",
           "GLS_DK",
           "GLS_FR",
           "RMG_UK",
           "GLS_SI",
           "KLEINANZEIGEN_DE"
          ],
          "example": "GLS_DE"
         },
         "provider_payload": {
          "type": "object",
          "additionalProperties": true,
          "description": "Required for AMAZON_DE and CAINIAO_FR. GLS/NXT supplies the payload. Do not include this field for KEBA and other providers that do not need it.\n"
         }
        }
       },
       "example": {
        "provider_locker_id": "<PROVIDER_LOCKER_ID>",
        "provider_name": "BLOQ",
        "carrier_name": "GLS_DE",
        "locker_status": "ACTIVE"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Request accepted. This does not confirm that the platform applied the event: the mock sends the event a few seconds later. Check the result in your Locker Updates webhooks or with `GET /lockers/by-uid`.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "x-internal": true,
         "required": [
          "message"
         ],
         "properties": {
          "message": {
           "type": "string",
           "example": "Locker event triggered successfully"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/mock_trigger_400"
     },
     "401": {
      "$ref": "#/components/responses/gateway_401"
     }
    }
   }
  },
  "/parcel/events/{id}": {
   "get": {
    "tags": [
     "Mock Service API"
    ],
    "summary": "Get received parcel events",
    "description": "Returns the Parcel Updates webhook bodies that the mock received for one parcel, oldest first.\nThe mock receives these webhooks only for carriers whose staging webhook URL points at the mock, and stores only events for test lockers (`carrierLockerId` starts with `996633`; without `carrierLockerId`, `lockerUid`).\nEach event is kept for one hour.\nThe response is an empty array when the mock has no event yet. Poll until the event that you expect arrives.",
    "operationId": "getParcelEvents",
    "servers": [
     {
      "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
      "description": "Staging mock service"
     }
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Your parcel ID (`carrierParcelId`).",
      "schema": {
       "type": "string",
       "example": "000123456789"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The stored parcel events. The array is empty when the mock has no event for this parcel.",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "x-internal": true,
         "items": {
          "$ref": "#/components/schemas/mock_parcel_event"
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/mock_event_query_400"
     },
     "401": {
      "$ref": "#/components/responses/gateway_401"
     },
     "500": {
      "$ref": "#/components/responses/mock_event_query_500"
     }
    }
   }
  },
  "/locker/events/{lockerUid}": {
   "get": {
    "tags": [
     "Mock Service API"
    ],
    "summary": "Get received locker events",
    "description": "Returns the Locker Updates webhook bodies that the mock received for one locker, oldest first.\nThe mock receives these webhooks only for carriers whose staging webhook URL points at the mock, and stores only events for test lockers (`carrier.lockerId` starts with `996633`; without `carrier.lockerId`, `uid`).\nEach event is kept for one hour.\nThe response is an empty array when the mock has no event yet. Poll until the event that you expect arrives.",
    "operationId": "getLockerEvents",
    "servers": [
     {
      "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
      "description": "Staging mock service"
     }
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "parameters": [
     {
      "name": "lockerUid",
      "in": "path",
      "required": true,
      "description": "The platform `lockerUid` (`uid` in the Locker Updates webhook).",
      "schema": {
       "type": "string",
       "example": "1002377838"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The stored locker events. The array is empty when the mock has no event for this locker.",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "x-internal": true,
         "items": {
          "$ref": "#/components/schemas/mock_locker_event"
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/mock_event_query_400"
     },
     "401": {
      "$ref": "#/components/responses/gateway_401"
     },
     "500": {
      "$ref": "#/components/responses/mock_event_query_500"
     }
    }
   }
  },
  "/collection/events/{lockerUid}": {
   "get": {
    "tags": [
     "Mock Service API"
    ],
    "summary": "Get received collection events",
    "description": "Returns the Collection Notification webhook bodies that the mock received for one locker, oldest first.\nThe mock receives these webhooks only for carriers whose staging webhook URL points at the mock, and stores only events for test lockers (`carrierLockerId` starts with `996633`).\nEach event is kept for one hour.\nThe response is an empty array when the mock has no event yet. Poll until the event that you expect arrives.",
    "operationId": "getCollectionEvents",
    "servers": [
     {
      "url": "https://api.staging.glsnxt.com/ooh-mock-service/v1",
      "description": "Staging mock service"
     }
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "parameters": [
     {
      "name": "lockerUid",
      "in": "path",
      "required": true,
      "description": "The platform `lockerUid` of the locker.",
      "schema": {
       "type": "string",
       "example": "1002377838"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The stored collection events. The array is empty when the mock has no event for this locker.",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "x-internal": true,
         "items": {
          "$ref": "#/components/schemas/mock_collection_event"
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/mock_event_query_400"
     },
     "401": {
      "$ref": "#/components/responses/gateway_401"
     },
     "500": {
      "$ref": "#/components/responses/mock_event_query_500"
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "ApiKeyAuth": {
    "type": "apiKey",
    "name": "X-API-Key",
    "in": "header",
    "description": "API Authorization Key for API access"
   }
  },
  "schemas": {
   "status": {
    "type": "string",
    "enum": [
     "ACTIVE",
     "INACTIVE",
     "MAINTENANCE",
     "DECOMMISSIONED",
     "INITIAL",
     "PLANNED"
    ],
    "example": "ACTIVE"
   },
   "compartment_size": {
    "type": "string",
    "description": "Locker compartment size.",
    "enum": [
     "XXSMALL",
     "XSMALL",
     "SMALL",
     "XMEDIUM",
     "MEDIUM",
     "LARGE",
     "XLARGE",
     "XXLARGE",
     "ULARGE",
     "UULARGE"
    ],
    "example": "MEDIUM"
   },
   "location": {
    "type": "object",
    "description": "Details about the geographical location of the locker.",
    "properties": {
     "street": {
      "type": "string",
      "description": "The street name where the locker is located.",
      "example": "Main Street"
     },
     "streetNumber": {
      "type": "string",
      "description": "The street number of the locker location.",
      "example": "1"
     },
     "postalCode": {
      "type": "string",
      "description": "The postal code of the locker location.",
      "example": "90210"
     },
     "city": {
      "type": "string",
      "description": "The city where the locker is located.",
      "example": "Berlin"
     },
     "lon": {
      "type": "number",
      "format": "double",
      "description": "The longitude coordinate of the locker location.",
      "example": -118.2437
     },
     "lat": {
      "type": "number",
      "format": "double",
      "description": "The latitude coordinate of the locker location.",
      "example": 34.0522
     },
     "countryCode": {
      "type": "string",
      "description": "The ISO 3166-1 alpha-2 country code for the locker location.",
      "example": "DE"
     },
     "type": {
      "type": "string",
      "enum": [
       "indoor",
       "outdoor"
      ],
      "description": "Optional location type indicating whether the locker is indoors or outdoors. Omitted when unspecified.",
      "example": "indoor"
     }
    },
    "required": [
     "street",
     "postalCode",
     "city",
     "lon",
     "lat",
     "countryCode"
    ]
   },
   "features": {
    "type": "object",
    "description": "Features available in the locker.",
    "properties": {
     "hasScreen": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "Indicates if the locker has a screen.",
      "example": true
     },
     "hasPinPad": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "Indicates if the locker has a PIN pad.",
      "example": true
     },
     "hasPinBarcodeReader": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "Indicates if the locker has a barcode reader.",
      "example": false
     }
    }
   },
   "period": {
    "type": "object",
    "required": [
     "open",
     "close"
    ],
    "properties": {
     "open": {
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
      "example": "08:00",
      "description": "Local opening time (inclusive)"
     },
     "close": {
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
      "example": "20:00",
      "description": "Local closing time (exclusive)"
     }
    }
   },
   "weekly_period": {
    "type": "object",
    "required": [
     "weekday",
     "periods"
    ],
    "properties": {
     "weekday": {
      "type": "string",
      "enum": [
       "MONDAY",
       "TUESDAY",
       "WEDNESDAY",
       "THURSDAY",
       "FRIDAY",
       "SATURDAY",
       "SUNDAY"
      ]
     },
     "periods": {
      "type": "array",
      "minItems": 1,
      "items": {
       "$ref": "#/components/schemas/period"
      }
     }
    }
   },
   "exception_period": {
    "type": "object",
    "description": "A date range overriding the default weekly schedule.\n\nConditional constraint (enforced server-side, not by the generated client):\n- Exactly one of `isClosed` (set to `true`) or `schedule` MUST be present.\n  Sending both, neither, or `isClosed: false` is a contract violation.\n",
    "required": [
     "startDate",
     "endDate"
    ],
    "properties": {
     "startDate": {
      "type": "string",
      "format": "date",
      "example": "2026-12-25"
     },
     "endDate": {
      "type": "string",
      "format": "date",
      "example": "2026-12-25"
     },
     "isClosed": {
      "type": "boolean",
      "description": "Marker flag indicating the locker is fully inaccessible for this range.\nWhen present it MUST be `true`; otherwise omit the field entirely.\nMutually exclusive with `schedule`.\n"
     },
     "schedule": {
      "type": "array",
      "minItems": 1,
      "description": "Overrides for specific weekdays within the exception range.\nMutually exclusive with `isClosed` — omit this field when `isClosed` is set.\n",
      "items": {
       "$ref": "#/components/schemas/weekly_period"
      },
      "example": [
       {
        "weekday": "MONDAY",
        "periods": [
         {
          "open": "10:00",
          "close": "16:00"
         }
        ]
       }
      ]
     }
    }
   },
   "opening_hours": {
    "type": "object",
    "description": "Locker availability schedule.\n\nConditional constraints (enforced server-side, not by the generated client):\n- If `accessMode` is `SCHEDULED`, `weeklySchedule` MUST be provided and non-empty.\n- If `accessMode` is `ALWAYS`, `weeklySchedule` MUST be omitted.\n",
    "required": [
     "accessMode"
    ],
    "properties": {
     "accessMode": {
      "type": "string",
      "enum": [
       "ALWAYS",
       "SCHEDULED"
      ],
      "description": "General availability mode.\n- `ALWAYS`: locker is always accessible; `weeklySchedule` must be omitted.\n- `SCHEDULED`: locker follows `weeklySchedule` (and any `exceptions`).\n"
     },
     "weeklySchedule": {
      "type": "array",
      "description": "Default schedule per weekday. Required and non-empty when `accessMode` is `SCHEDULED`; must be omitted when `accessMode` is `ALWAYS`.",
      "minItems": 1,
      "items": {
       "$ref": "#/components/schemas/weekly_period"
      }
     },
     "exceptions": {
      "type": "array",
      "description": "Overrides for specific dates (holidays, maintenance, seasonal hours). Ignored when `accessMode` is `ALWAYS`.",
      "items": {
       "$ref": "#/components/schemas/exception_period"
      }
     }
    },
    "$defs": {
     "weekly_period": {
      "type": "object",
      "required": [
       "weekday",
       "periods"
      ],
      "properties": {
       "weekday": {
        "type": "string",
        "enum": [
         "MONDAY",
         "TUESDAY",
         "WEDNESDAY",
         "THURSDAY",
         "FRIDAY",
         "SATURDAY",
         "SUNDAY"
        ]
       },
       "periods": {
        "type": "array",
        "minItems": 1,
        "items": {
         "$ref": "#/components/schemas/period"
        }
       }
      }
     },
     "period": {
      "type": "object",
      "required": [
       "open",
       "close"
      ],
      "properties": {
       "open": {
        "type": "string",
        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
        "example": "08:00",
        "description": "Local opening time (inclusive)"
       },
       "close": {
        "type": "string",
        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
        "example": "20:00",
        "description": "Local closing time (exclusive)"
       }
      }
     },
     "exception_period": {
      "type": "object",
      "description": "A date range overriding the default weekly schedule.\n\nConditional constraint (enforced server-side, not by the generated client):\n- Exactly one of `isClosed` (set to `true`) or `schedule` MUST be present.\n  Sending both, neither, or `isClosed: false` is a contract violation.\n",
      "required": [
       "startDate",
       "endDate"
      ],
      "properties": {
       "startDate": {
        "type": "string",
        "format": "date",
        "example": "2026-12-25"
       },
       "endDate": {
        "type": "string",
        "format": "date",
        "example": "2026-12-25"
       },
       "isClosed": {
        "type": "boolean",
        "description": "Marker flag indicating the locker is fully inaccessible for this range.\nWhen present it MUST be `true`; otherwise omit the field entirely.\nMutually exclusive with `schedule`.\n"
       },
       "schedule": {
        "type": "array",
        "minItems": 1,
        "description": "Overrides for specific weekdays within the exception range.\nMutually exclusive with `isClosed` — omit this field when `isClosed` is set.\n",
        "items": {
         "$ref": "#/components/schemas/weekly_period"
        },
        "example": [
         {
          "weekday": "MONDAY",
          "periods": [
           {
            "open": "10:00",
            "close": "16:00"
           }
          ]
         }
        ]
       }
      }
     }
    }
   },
   "metadata": {
    "type": "object",
    "description": "Metadata associated with the locker.",
    "properties": {
     "key": {
      "type": [
       "string",
       "null"
      ],
      "description": "The key of the metadata.",
      "example": "maxWeightCapacity"
     },
     "value": {
      "type": [
       "string",
       "null"
      ],
      "description": "The value of the metadata.",
      "example": "50kg"
     }
    }
   },
   "compartment": {
    "type": "object",
    "description": "Details about the compartments available in the locker.",
    "properties": {
     "size": {
      "description": "The size of the compartment. It is null when the stored size is not one of the known sizes.",
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "XXSMALL",
       "XSMALL",
       "SMALL",
       "XMEDIUM",
       "MEDIUM",
       "LARGE",
       "XLARGE",
       "XXLARGE",
       "ULARGE",
       "UULARGE",
       null
      ],
      "example": "MEDIUM"
     },
     "count": {
      "type": "integer",
      "description": "The number of compartments of this size available in the locker.",
      "example": 4
     },
     "height": {
      "type": "integer",
      "description": "The height of the compartment in millimeters.",
      "example": 400
     },
     "width": {
      "type": "integer",
      "description": "The width of the compartment in millimeters.",
      "example": 400
     },
     "length": {
      "type": "integer",
      "description": "The length of the compartment in millimeters.",
      "example": 600
     }
    }
   },
   "locker_response": {
    "type": "object",
    "properties": {
     "uid": {
      "type": "string",
      "description": "The internal unique identifier assigned to the locker.",
      "example": "1002377838"
     },
     "carrier": {
      "type": "object",
      "description": "The details of the locker on the Carrier's system.",
      "properties": {
       "lockerName": {
        "type": "string",
        "description": "The name assigned to the locker on the Carrier's system.",
        "example": "Berlin Locker 01"
       },
       "lockerId": {
        "type": [
         "string",
         "null"
        ],
        "description": "The identifier of the locker on the Carrier's system. `null` when the carrier has not set one.",
        "example": "XR1003"
       },
       "activationDate": {
        "type": [
         "string",
         "null"
        ],
        "format": "date-time",
        "description": "The date when the locker is to be activated for the carrier. `null` when not set.",
        "example": "2025-08-20T00:00:00Z"
       },
       "status": {
        "$ref": "#/components/schemas/status"
       }
      },
      "required": [
       "lockerName",
       "lockerId"
      ]
     },
     "provider": {
      "type": "object",
      "description": "The details of the locker on the Provider's system.",
      "properties": {
       "name": {
        "type": "string",
        "description": "The name of the locker provider.",
        "example": "KEBA"
       },
       "lockerModel": {
        "type": [
         "string",
         "null"
        ],
        "description": "The model of the locker provided by the provider. `null` when the provider has not sent one.",
        "example": "Model 1"
       },
       "lockerVersion": {
        "type": [
         "string",
         "null"
        ],
        "description": "The version of the locker model provided by the provider. `null` when the provider has not sent one.",
        "example": "v2.1"
       },
       "lockerName": {
        "type": "string",
        "description": "The name of the locker on the Provider's system.",
        "example": "BLOQ-Berlin-12045-001"
       },
       "lockerUid": {
        "type": "string",
        "description": "The unique identifier of the locker on the Provider's system.",
        "example": "PROVIDER_LOCKER_ABC123"
       },
       "status": {
        "type": "string",
        "description": "The status of the locker returned by the provider.",
        "enum": [
         "ACTIVE",
         "INACTIVE",
         "PLANNED"
        ],
        "example": "ACTIVE"
       }
      },
      "required": [
       "name",
       "lockerModel",
       "lockerVersion",
       "status"
      ]
     },
     "location": {
      "$ref": "#/components/schemas/location"
     },
     "features": {
      "description": "Features available in the locker. `null` when the locker has no feature data.",
      "oneOf": [
       {
        "$ref": "#/components/schemas/features"
       },
       {
        "type": "null"
       }
      ]
     },
     "openingHours": {
      "$ref": "#/components/schemas/opening_hours"
     },
     "metadata": {
      "type": [
       "array",
       "null"
      ],
      "description": "Additional metadata associated with the locker. `null` when the carrier locker has none.",
      "items": {
       "$ref": "#/components/schemas/metadata"
      }
     },
     "ownedByCarrier": {
      "type": [
       "string",
       "null"
      ],
      "description": "Indicates which carrier owns the locker. `null` means the locker belongs to a 3rd party provider.",
      "example": "GLS"
     },
     "compartmentTypes": {
      "type": [
       "array",
       "null"
      ],
      "description": "A list of different compartment types available in the locker.",
      "items": {
       "$ref": "#/components/schemas/compartment"
      },
      "example": [
       {
        "size": "SMALL",
        "count": 10,
        "height": 200,
        "width": 400,
        "length": 600
       },
       {
        "size": "MEDIUM",
        "count": 4,
        "height": 400,
        "width": 400,
        "length": 600
       },
       {
        "size": "LARGE",
        "count": 2,
        "height": 800,
        "width": 400,
        "length": 600
       }
      ]
     }
    },
    "required": [
     "uid",
     "carrier",
     "provider",
     "location"
    ]
   },
   "gateway_error": {
    "type": "object",
    "properties": {
     "message": {
      "type": "string",
      "description": "A message describing the error.",
      "example": "Unauthorized"
     },
     "request_id": {
      "type": "string",
      "description": "The identifier of the request at the API gateway. Include it when you report a problem.",
      "example": "a1eff468e84bcd6bbe3620047a6d5967"
     }
    },
    "required": [
     "message"
    ]
   },
   "carrier": {
    "type": "object",
    "description": "The details of the locker on the Carrier's system.",
    "properties": {
     "lockerName": {
      "type": "string",
      "description": "The name assigned to the locker on the Carrier's system.",
      "example": "Berlin Locker 01"
     },
     "lockerId": {
      "type": "string",
      "description": "The identifier of the locker on the Carrier's system.",
      "example": "XR1003"
     },
     "activationDate": {
      "type": "string",
      "format": "date-time",
      "description": "The date when the locker is to be activated for the carrier.",
      "example": "2025-08-20T00:00:00Z"
     }
    },
    "required": [
     "lockerName",
     "lockerId"
    ]
   },
   "carrier_input": {
    "description": "The carrier's details for the locker. Requests use these fields in addition to the shared carrier fields.",
    "allOf": [
     {
      "$ref": "#/components/schemas/carrier"
     },
     {
      "type": "object",
      "properties": {
       "mdmLockerId": {
        "type": "string",
        "description": "The identifier of the locker in the carrier's master data management system.",
        "example": "MDM-12345"
       },
       "dropoffBarcodeId": {
        "type": "string",
        "description": "The barcode identifier a courier scans to drop off parcels at this locker.",
        "example": "DROP-0001"
       },
       "checkoutLockerId": {
        "type": "string",
        "description": "The identifier of the locker in the carrier's checkout system.",
        "example": "CHK-0001"
       }
      }
     }
    ]
   },
   "provider": {
    "type": "object",
    "description": "The details of the locker on the Provider's system.",
    "properties": {
     "name": {
      "type": "string",
      "description": "The name of the locker provider.",
      "example": "KEBA"
     },
     "lockerModel": {
      "type": "string",
      "description": "The model of the locker provided by the provider.",
      "example": "Model 1"
     },
     "lockerVersion": {
      "type": "string",
      "description": "The version of the locker model provided by the provider.",
      "example": "v2.1"
     }
    },
    "required": [
     "name",
     "lockerModel",
     "lockerVersion"
    ]
   },
   "provider_input": {
    "description": "The provider's details for the locker. Requests use these fields in addition to the shared provider fields.",
    "allOf": [
     {
      "$ref": "#/components/schemas/provider"
     },
     {
      "type": "object",
      "properties": {
       "configurationName": {
        "type": "string",
        "description": "The name of the provider configuration to use for this locker.",
        "example": "default",
        "pattern": "^[A-Za-z0-9_.-]{1,64}$",
        "maxLength": 64
       }
      }
     }
    ]
   },
   "metadata_input": {
    "type": "object",
    "description": "A metadata entry to set on the locker. Both fields are required.",
    "required": [
     "key",
     "value"
    ],
    "properties": {
     "key": {
      "type": "string",
      "description": "The key of the metadata.",
      "example": "maxWeightCapacity"
     },
     "value": {
      "type": "string",
      "description": "The value of the metadata.",
      "example": "50kg"
     }
    }
   },
   "group": {
    "type": "object",
    "description": "Reference to a locker group to assign, identified by its type key and uid.",
    "properties": {
     "key": {
      "type": "string",
      "description": "The locker group type key. A locker may have at most one group per key.",
      "example": "DEPOT"
     },
     "uid": {
      "type": "string",
      "description": "The uid of the locker group.",
      "example": "6838265090"
     }
    },
    "required": [
     "key",
     "uid"
    ]
   },
   "create_input": {
    "type": "object",
    "properties": {
     "carrier": {
      "$ref": "#/components/schemas/carrier_input"
     },
     "provider": {
      "$ref": "#/components/schemas/provider_input"
     },
     "location": {
      "$ref": "#/components/schemas/location"
     },
     "metadata": {
      "type": "array",
      "description": "Additional metadata associated with the locker.",
      "items": {
       "$ref": "#/components/schemas/metadata_input"
      }
     },
     "features": {
      "$ref": "#/components/schemas/features"
     },
     "lockerGroups": {
      "type": "array",
      "description": "Locker groups to assign, identified by key and uid; at most one per type key.",
      "items": {
       "$ref": "#/components/schemas/group"
      }
     }
    },
    "required": [
     "carrier",
     "provider",
     "location"
    ]
   },
   "response_409": {
    "type": "object",
    "properties": {
     "errorCode": {
      "type": "string",
      "description": "A code representing the type of error.",
      "example": "CONFLICT"
     },
     "message": {
      "type": "string",
      "description": "A message describing the error.",
      "example": "The request conflicts with the current state of the resource"
     }
    }
   },
   "provider_update_input": {
    "type": "object",
    "description": "The provider fields a locker update can change.",
    "properties": {
     "configurationName": {
      "type": "string",
      "description": "The name of the provider configuration to use for this locker.",
      "example": "default",
      "pattern": "^[A-Za-z0-9_.-]{1,64}$",
      "maxLength": 64
     }
    }
   },
   "update_input": {
    "type": "object",
    "properties": {
     "carrier": {
      "$ref": "#/components/schemas/carrier_input"
     },
     "location": {
      "$ref": "#/components/schemas/location"
     },
     "metadata": {
      "type": "array",
      "description": "Additional metadata associated with the locker.",
      "items": {
       "$ref": "#/components/schemas/metadata_input"
      }
     },
     "features": {
      "$ref": "#/components/schemas/features"
     },
     "lockerGroups": {
      "type": "array",
      "description": "Locker groups to assign, identified by key and uid; at most one per type key. Omit to leave current groups unchanged.",
      "items": {
       "$ref": "#/components/schemas/group"
      }
     },
     "provider": {
      "$ref": "#/components/schemas/provider_update_input"
     }
    }
   },
   "update_status": {
    "type": "object",
    "properties": {
     "lockerUid": {
      "type": "string",
      "example": "678438790243767",
      "description": "The unique identifier of the locker in the GLS/NXT Platform"
     },
     "status": {
      "$ref": "#/components/schemas/status"
     }
    },
    "required": [
     "lockerUid",
     "status"
    ]
   },
   "locker_group_type": {
    "type": "object",
    "description": "A locker group type from the global catalog.",
    "properties": {
     "key": {
      "type": "string",
      "description": "The unique key identifying the locker group type.",
      "example": "DEPOT"
     },
     "category": {
      "type": "string",
      "description": "The category the locker group type belongs to.",
      "example": "DISTRIBUTION_CENTER"
     }
    },
    "required": [
     "key",
     "category"
    ]
   },
   "locker_group": {
    "type": "object",
    "description": "A locker group owned by the carrier.",
    "properties": {
     "uid": {
      "type": "string",
      "description": "The unique identifier of the locker group.",
      "example": "6838265090"
     },
     "key": {
      "type": "string",
      "description": "The locker group type key. A locker may belong to at most one group per key.",
      "example": "DEPOT"
     },
     "category": {
      "type": "string",
      "description": "The category the locker group type belongs to.",
      "example": "DISTRIBUTION_CENTER"
     },
     "name": {
      "type": "string",
      "description": "The name of the locker group.",
      "example": "Berlin Central"
     }
    },
    "required": [
     "key",
     "category",
     "name"
    ]
   },
   "locker_group_create_request": {
    "type": "object",
    "description": "Request to create a locker group.",
    "properties": {
     "typeKey": {
      "type": "string",
      "description": "The locker group type key from the global catalog.",
      "example": "DEPOT"
     },
     "name": {
      "type": "string",
      "description": "The name of the locker group.",
      "example": "Berlin Central"
     }
    },
    "required": [
     "typeKey",
     "name"
    ]
   },
   "locker_group_update_request": {
    "type": "object",
    "description": "Request to update a locker group.",
    "properties": {
     "name": {
      "type": "string",
      "description": "The new name of the locker group.",
      "example": "Berlin North"
     }
    },
    "required": [
     "name"
    ]
   },
   "locker_group_add_request": {
    "type": "object",
    "description": "Request to assign lockers to a locker group.",
    "properties": {
     "lockerUids": {
      "type": "array",
      "description": "The UIDs of the lockers to assign to the group.",
      "items": {
       "type": "string"
      },
      "example": [
       "10000019",
       "10000020"
      ]
     }
    },
    "required": [
     "lockerUids"
    ]
   },
   "locker_group_add_response": {
    "type": "object",
    "description": "The lockers that were assigned to the locker group.",
    "properties": {
     "lockersAdded": {
      "type": "array",
      "description": "The UIDs of the lockers that were assigned to the group.",
      "items": {
       "type": "string"
      },
      "example": [
       "10000019",
       "10000020"
      ]
     }
    },
    "required": [
     "lockersAdded"
    ]
   },
   "locker_group_remove_request": {
    "type": "object",
    "description": "Request to remove lockers from a locker group.",
    "properties": {
     "lockerUids": {
      "type": "array",
      "description": "The UIDs of the lockers to remove from the group.",
      "items": {
       "type": "string"
      },
      "example": [
       "10000019"
      ]
     }
    },
    "required": [
     "lockerUids"
    ]
   },
   "locker_group_removed_response": {
    "type": "object",
    "description": "The lockers that were removed from the locker group.",
    "properties": {
     "lockersRemoved": {
      "type": "array",
      "description": "The UIDs of the lockers that were removed from the group.",
      "items": {
       "type": "string"
      },
      "example": [
       "10000019"
      ]
     }
    },
    "required": [
     "lockersRemoved"
    ]
   },
   "network": {
    "type": "object",
    "description": "A network connecting a locker owner carrier with a tenant carrier.",
    "properties": {
     "uid": {
      "type": "integer",
      "format": "int64",
      "description": "The unique identifier of the network.",
      "example": 8065713862
     },
     "ownedBy": {
      "type": "string",
      "description": "The carrier that owns the network.",
      "example": "GLS_NXT"
     },
     "tenant": {
      "type": "string",
      "description": "The carrier that is the tenant of the network.",
      "example": "GLS_DE"
     },
     "autoShare": {
      "type": "boolean",
      "description": "When true, new lockers owned by this carrier are automatically added to the network.",
      "example": false
     }
    },
    "required": [
     "uid",
     "ownedBy",
     "tenant",
     "autoShare"
    ]
   },
   "network_locker": {
    "type": "object",
    "description": "A locker within a network, including its status from the provider, carrier, and network perspectives.",
    "properties": {
     "lockerUid": {
      "type": "integer",
      "format": "int64",
      "description": "The unique identifier of the locker.",
      "example": 10000019
     },
     "providerName": {
      "type": "string",
      "description": "The name of the locker provider.",
      "example": "MYFLEXBOX_DE"
     },
     "lockerName": {
      "type": [
       "string",
       "null"
      ],
      "description": "The carrier-assigned name for the locker.",
      "example": "Berlin Hauptbahnhof"
     },
     "providerLockerStatus": {
      "type": "string",
      "description": "The current status of the locker on the provider's side.",
      "example": "ACTIVE"
     },
     "carrierLockerStatus": {
      "type": [
       "string",
       "null"
      ],
      "description": "The status of the locker for the carrier.",
      "example": "ACTIVE"
     },
     "networkLockerStatus": {
      "type": [
       "string",
       "null"
      ],
      "description": "The status of the locker within the network.",
      "example": "PENDING"
     },
     "carrierLockerId": {
      "type": [
       "string",
       "null"
      ],
      "description": "The carrier-specific locker identifier.",
      "example": "3001"
     },
     "providerLockerId": {
      "type": [
       "string",
       "null"
      ],
      "description": "The provider-specific locker identifier.",
      "example": "68958"
     }
    },
    "required": [
     "lockerUid",
     "providerName",
     "providerLockerStatus"
    ]
   },
   "network_locker_page": {
    "type": "object",
    "description": "A paginated list of network lockers.",
    "properties": {
     "content": {
      "type": "array",
      "description": "The list of network lockers for the current page.",
      "items": {
       "$ref": "#/components/schemas/network_locker"
      }
     },
     "pageNumber": {
      "type": "integer",
      "format": "int32",
      "description": "The current page number (1-based).",
      "example": 1
     },
     "pageSize": {
      "type": "integer",
      "format": "int32",
      "description": "The number of items per page.",
      "example": 100
     },
     "totalElements": {
      "type": "integer",
      "format": "int64",
      "description": "The total number of lockers across all pages.",
      "example": 3
     },
     "isLast": {
      "type": "boolean",
      "description": "Whether this is the last page.",
      "example": true
     }
    },
    "required": [
     "content",
     "pageNumber",
     "pageSize",
     "totalElements",
     "isLast"
    ]
   },
   "network_locker_add_request": {
    "type": "object",
    "description": "Request to add lockers to a network.",
    "properties": {
     "lockerUids": {
      "type": "array",
      "description": "The list of locker UIDs to add to the network.",
      "items": {
       "type": "integer",
       "format": "int64"
      },
      "example": [
       10000019,
       10000020,
       10000021
      ]
     }
    },
    "required": [
     "lockerUids"
    ]
   },
   "network_locker_remove_request": {
    "type": "object",
    "description": "Request to remove lockers from a network.",
    "properties": {
     "lockerUids": {
      "type": "array",
      "description": "The list of locker UIDs to remove from the network.",
      "items": {
       "type": "integer",
       "format": "int64"
      },
      "example": [
       10000019,
       10000020
      ]
     }
    },
    "required": [
     "lockerUids"
    ]
   },
   "carrier_update": {
    "type": "object",
    "description": "Optional carrier details to update for a network locker.",
    "properties": {
     "lockerName": {
      "type": "string",
      "description": "The name assigned to the locker on the Carrier's system.",
      "example": "Berlin Locker 01"
     },
     "lockerId": {
      "type": "string",
      "description": "The identifier of the locker on the Carrier's system.",
      "example": "XR1003"
     },
     "activationDate": {
      "type": "string",
      "description": "The date when the locker is to be activated for the carrier.",
      "example": "2025-08-20T00:00:00Z"
     }
    }
   },
   "network_locker_patch": {
    "type": "object",
    "description": "Request to update the status of a locker within a network, optionally including carrier details.",
    "properties": {
     "networkLockerStatus": {
      "type": "string",
      "description": "The new status for the network locker.",
      "example": "ACCEPTED"
     },
     "carrier": {
      "$ref": "#/components/schemas/carrier_update"
     }
    },
    "required": [
     "networkLockerStatus"
    ]
   },
   "booking_type": {
    "type": "string",
    "description": "The type of booking request.",
    "enum": [
     "PRE_CHECK",
     "BOOKING"
    ],
    "example": "BOOKING"
   },
   "shipment_type_input": {
    "type": "string",
    "description": "The possible types of last-mile shipments accepted. Defaults to `LAST_MILE` when not present.",
    "enum": [
     "LAST_MILE",
     "ALTERNATIVE_DELIVERY"
    ],
    "example": "LAST_MILE"
   },
   "consignee": {
    "type": [
     "object",
     "null"
    ],
    "description": "The details of the consignee.",
    "properties": {
     "name": {
      "type": [
       "string",
       "null"
      ],
      "example": "John Doe"
     },
     "email": {
      "type": [
       "string",
       "null"
      ],
      "format": "email",
      "example": "john.doe@google.com"
     }
    }
   },
   "dimensions": {
    "type": "object",
    "additionalProperties": false,
    "description": "The dimensions of the parcel. A missing field counts as unknown, and the platform uses 10 mm for it.",
    "properties": {
     "depth": {
      "type": [
       "integer",
       "null"
      ],
      "minimum": 1,
      "description": "Depth in mm",
      "example": 190
     },
     "height": {
      "type": [
       "integer",
       "null"
      ],
      "minimum": 1,
      "description": "Height in mm",
      "example": 100
     },
     "width": {
      "type": [
       "integer",
       "null"
      ],
      "minimum": 1,
      "description": "Width in mm",
      "example": 140
     }
    }
   },
   "allocation_type": {
    "type": "string",
    "description": "The allocation type of the shipment.",
    "enum": [
     "HARD_RESERVATION",
     "SOFT_RESERVATION"
    ],
    "example": "HARD_RESERVATION"
   },
   "input_data": {
    "type": "object",
    "additionalProperties": false,
    "description": "If you send `consignee`, send both `name` and `email` as strings, and no other fields. The platform rejects a consignee with a missing, null or unknown field.",
    "properties": {
     "eventType": {
      "$ref": "#/components/schemas/booking_type"
     },
     "lockerUid": {
      "type": "string",
      "description": "The unique identifier of the locker in the GLS/NXT Platform.",
      "example": "locker_567890"
     },
     "carrierParcelId": {
      "type": "string",
      "description": "The identifier of the parcel in the carrier's system.",
      "example": "A123456789"
     },
     "shipmentType": {
      "$ref": "#/components/schemas/shipment_type_input"
     },
     "consignee": {
      "$ref": "#/components/schemas/consignee"
     },
     "dimensions": {
      "$ref": "#/components/schemas/dimensions"
     },
     "weight": {
      "type": "integer",
      "description": "Weight in grams",
      "example": 400
     },
     "allocationType": {
      "$ref": "#/components/schemas/allocation_type"
     },
     "requiresAccessibleCompartment": {
      "type": "boolean",
      "description": "Indicates whether the parcel requires an accessible compartment. Defaults to false when not present or null.",
      "default": false,
      "example": false
     },
     "secondaryShipmentId": {
      "type": "string",
      "description": "A secondary identifier for the shipment, separate from carrierParcelId.",
      "example": "EXP-CODE-0001"
     },
     "codAmount": {
      "type": "integer",
      "format": "int64",
      "description": "Cash-on-delivery amount to collect, expressed in minor units (e.g. cents).",
      "example": 2450
     },
     "codCurrency": {
      "type": "string",
      "description": "ISO 4217 currency code for `codAmount`.",
      "example": "EUR"
     },
     "lockStatus": {
      "type": "string",
      "enum": [
       "LOCKED",
       "UNLOCKED"
      ],
      "description": "The lock state to apply to the parcel on booking. `LOCKED` blocks the consignee from collecting the parcel; `UNLOCKED` releases it for collection.",
      "example": "LOCKED"
     }
    },
    "required": [
     "eventType",
     "carrierParcelId",
     "lockerUid",
     "dimensions"
    ]
   },
   "input_data_response": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "description": "The status of the event processing.",
      "example": "success"
     },
     "message": {
      "type": "string",
      "description": "A message providing additional information about the event processing.",
      "example": "Parcel event received and processed successfully."
     },
     "timestamp": {
      "type": "string",
      "format": "date-time",
      "description": "The timestamp when the event was processed.",
      "example": "2023-06-18T10:45:00Z"
     }
    },
    "required": [
     "status",
     "message",
     "timestamp"
    ]
   },
   "parcel_input_error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "string",
      "description": "A message describing the error.",
      "example": "Failed to parse request"
     }
    },
    "required": [
     "error"
    ]
   },
   "input_data_carrier_specific": {
    "type": "object",
    "additionalProperties": false,
    "description": "If you send `consignee`, send both `name` and `email` as strings, and no other fields. The platform rejects a consignee with a missing, null or unknown field.",
    "properties": {
     "eventType": {
      "$ref": "#/components/schemas/booking_type"
     },
     "carrierLockerId": {
      "type": "string",
      "description": "The unique identifier of the locker in the Carrier Platform.",
      "example": "LOCKER123"
     },
     "carrierParcelId": {
      "type": "string",
      "description": "The identifier of the parcel in the carrier's system.",
      "example": "12345KL6789M"
     },
     "shipmentType": {
      "$ref": "#/components/schemas/shipment_type_input"
     },
     "consignee": {
      "$ref": "#/components/schemas/consignee"
     },
     "dimensions": {
      "$ref": "#/components/schemas/dimensions"
     },
     "weight": {
      "type": "integer",
      "description": "Weight in grams",
      "example": 300
     },
     "allocationType": {
      "$ref": "#/components/schemas/allocation_type"
     },
     "requiresAccessibleCompartment": {
      "type": "boolean",
      "description": "Indicates whether the parcel requires an accessible compartment. Defaults to false when not present or null.",
      "default": false,
      "example": false
     },
     "secondaryShipmentId": {
      "type": "string",
      "description": "A secondary identifier for the shipment, separate from carrierParcelId.",
      "example": "EXP-CODE-0001"
     },
     "codAmount": {
      "type": "integer",
      "format": "int64",
      "description": "Cash-on-delivery amount to collect, expressed in minor units (e.g. cents).",
      "example": 2450
     },
     "codCurrency": {
      "type": "string",
      "description": "ISO 4217 currency code for `codAmount`.",
      "example": "EUR"
     },
     "lockStatus": {
      "type": "string",
      "enum": [
       "LOCKED",
       "UNLOCKED"
      ],
      "description": "The lock state to apply to the parcel on booking. `LOCKED` blocks the consignee from collecting the parcel; `UNLOCKED` releases it for collection.",
      "example": "LOCKED"
     }
    },
    "required": [
     "eventType",
     "carrierParcelId",
     "carrierLockerId",
     "dimensions"
    ]
   },
   "shipment_type": {
    "type": "string",
    "description": "The type of shipment.",
    "enum": [
     "LAST_MILE",
     "ALTERNATIVE_DELIVERY",
     "FIRST_MILE",
     "RETURN"
    ],
    "example": "LAST_MILE"
   },
   "dimensions_status": {
    "type": "string",
    "description": "The status of the parcel dimensions. The parcel API sends `PARCEL_DIMENSIONS_EXCEEDED` for a parcel that is too big; webhooks send `PARCEL_DIMENSIONS_EXCEED`.",
    "enum": [
     "PARCEL_DIMENSIONS_EXCEED",
     "PARCEL_DIMENSIONS_EXCEEDED",
     "PARCEL_DIMENSIONS_OK",
     "PARCEL_DIMENSIONS_UNKNOWN"
    ],
    "example": "PARCEL_DIMENSIONS_OK"
   },
   "shipment_status": {
    "type": "string",
    "description": "The status of the shipment. `LOCKED`, `UNLOCKED` and `CONSIGNEE_PAID` are milestones in a parcel's `events`; they are never the parcel's `shipmentStatus`.",
    "enum": [
     "BOOKING_PRE_CHECK",
     "BOOKING_REQUESTED",
     "BOOKING_CREATED",
     "BOOKING_CANCELLED",
     "BOOKING_CANCELLATION_FAILED",
     "BOOKING_EXPIRED",
     "BOOKING_REJECTED_INVALID_LOCKER",
     "BOOKING_REJECTED_PROVIDER_ERROR",
     "BOOKING_REJECTED_LOCKER_IS_FULL",
     "BOOKING_REJECTED_NO_FREE_FITTING_COMPARTMENT",
     "BOOKING_REJECTED_LOCKER_UNAVAILABLE",
     "BOOKING_REJECTED_DIMENSIONS_EXCEED",
     "BOOKING_REJECTED_INVALID_CONSIGNEE",
     "BOOKING_REJECTED_NO_ACCESSIBLE_COMPARTMENT",
     "COURIER_DELIVERED",
     "COURIER_DELIVERY_EXPIRED",
     "COURIER_DELIVERY_LABEL_SCANNED",
     "COURIER_DELIVERY_ERROR",
     "COURIER_COLLECTED",
     "COURIER_COLLECTED_EXPIRED",
     "COURIER_COLLECTION_LABEL_SCANNED",
     "COURIER_COLLECTION_LABEL_NOT_AVAILABLE",
     "CONSIGNEE_COLLECTED",
     "CONSIGNEE_PAID",
     "CONSIGNEE_DELIVERED",
     "CONSIGNEE_DELIVERY_EXPIRED",
     "CONSIGNEE_COLLECTION_EXPIRED",
     "PARCEL_TO_BE_EXPIRED",
     "DELIVERY_PARCEL_TOO_BIG",
     "DELIVERY_COMPARTMENT_BROKEN",
     "DELIVERY_COMPARTMENT_OCCUPIED",
     "DELIVERY_NOT_POSSIBLE",
     "COLLECTION_PARCEL_NOT_AVAILABLE",
     "COLLECTION_COMPARTMENT_BROKEN",
     "COLLECTION_NOT_POSSIBLE",
     "MAINTENANCE_COLLECTED",
     "LOCKED",
     "UNLOCKED"
    ],
    "example": "CONSIGNEE_COLLECTED"
   },
   "code": {
    "type": [
     "object",
     "null"
    ],
    "description": "Access codes with valid until timestamp.",
    "properties": {
     "code": {
      "type": "string",
      "example": "anyValidCode123"
     },
     "validUntil": {
      "type": "string",
      "format": "date-time",
      "example": "2025-01-27T12:00:00Z",
      "description": "Code validity in UTC timestamp [ISO 8601](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) format."
     }
    },
    "required": [
     "code"
    ]
   },
   "access_codes": {
    "type": [
     "object",
     "null"
    ],
    "description": "Access codes for the parcel",
    "properties": {
     "consigneeCollection": {
      "type": "string",
      "example": "anyValidCode123",
      "deprecated": true
     },
     "consigneeCollectionCode": {
      "type": "object",
      "$ref": "#/components/schemas/code",
      "description": "The access code for the consignee collection"
     }
    }
   },
   "parcel_events": {
    "type": "array",
    "items": {
     "type": "object",
     "properties": {
      "timestamp": {
       "type": "string",
       "format": "date-time",
       "example": "2025-08-20T00:00:00Z"
      },
      "eventType": {
       "$ref": "#/components/schemas/shipment_status"
      }
     }
    }
   },
   "signature": {
    "type": [
     "object",
     "null"
    ],
    "description": "A Base64-encoded image representing the consignee's signature, captured upon parcel collection",
    "properties": {
     "imageBase64": {
      "type": "string",
      "example": "imageBase64StringHere"
     },
     "format": {
      "type": "string",
      "example": ""
     }
    }
   },
   "parcel_response": {
    "type": "object",
    "properties": {
     "shipmentUid": {
      "type": "string",
      "example": "anyParcelId123",
      "description": "The unique identifier of the parcel shipment in the GLS/NXT Platform"
     },
     "lockerUid": {
      "type": "string",
      "example": "anyLockerId123",
      "description": "The unique identifier of the locker in the GLS/NXT Platform"
     },
     "carrierParcelId": {
      "type": "string",
      "example": "anyCarrierParcelId123",
      "description": "The identifier of the parcel in the carrier's system"
     },
     "carrierLockerId": {
      "type": [
       "string",
       "null"
      ],
      "example": "Locker1",
      "description": "The identifier of the locker in the carrier's system"
     },
     "shipmentType": {
      "description": "The type of shipment. `null` when the platform received no shipment type for the parcel.",
      "anyOf": [
       {
        "$ref": "#/components/schemas/shipment_type"
       },
       {
        "type": "null"
       }
      ]
     },
     "dimensionsStatus": {
      "$ref": "#/components/schemas/dimensions_status"
     },
     "shipmentStatus": {
      "$ref": "#/components/schemas/shipment_status"
     },
     "isFinal": {
      "type": "boolean",
      "example": true
     },
     "accessCodes": {
      "$ref": "#/components/schemas/access_codes"
     },
     "consignee": {
      "$ref": "#/components/schemas/consignee"
     },
     "events": {
      "$ref": "#/components/schemas/parcel_events"
     },
     "allocationType": {
      "description": "The allocation type of the shipment. `null` when the platform received no allocation type for the parcel.",
      "anyOf": [
       {
        "$ref": "#/components/schemas/allocation_type"
       },
       {
        "type": "null"
       }
      ]
     },
     "providerName": {
      "type": [
       "string",
       "null"
      ],
      "example": "LOCKY_PT",
      "description": "The name of the locker network provider"
     },
     "providerLockerId": {
      "type": [
       "string",
       "null"
      ],
      "example": "1178",
      "description": "The identifier of the locker in the provider's system"
     },
     "shipmentSignature": {
      "$ref": "#/components/schemas/signature"
     },
     "requiresAccessibleCompartment": {
      "type": "boolean",
      "example": true
     },
     "labelType": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "LABELLESS",
       "LABELED",
       null
      ],
      "example": "LABELLESS",
      "description": "Label mode for the shipment. `LABELLESS` means no printed label is used and `LABELED` means a printed label is used."
     },
     "referenceCode": {
      "type": [
       "string",
       "null"
      ],
      "example": "LBL000000018",
      "description": "Reference code scanned by driver during pickup of the labelless parcel. This field is only relevant for `LABELLESS` shipments."
     },
     "secondaryShipmentId": {
      "type": [
       "string",
       "null"
      ],
      "example": "EXP-CODE-0001",
      "description": "A secondary identifier for the shipment, separate from `carrierParcelId`."
     },
     "paymentStatus": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "EXPECTED",
       "PAID",
       "FAILED",
       null
      ],
      "example": "PAID",
      "description": "The current cash-on-delivery payment status for the shipment, when applicable. Absent when the shipment carries no CoD payment."
     },
     "codAmount": {
      "type": [
       "integer",
       "null"
      ],
      "format": "int64",
      "example": 2450,
      "description": "Cash-on-delivery amount to collect, expressed in minor units (e.g. cents). Absent when the shipment carries no CoD payment."
     },
     "codCurrency": {
      "type": [
       "string",
       "null"
      ],
      "example": "EUR",
      "description": "ISO 4217 currency code for `codAmount`. Absent when the shipment carries no CoD payment."
     },
     "paymentType": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "CARD",
       "FLIK",
       null
      ],
      "example": "CARD",
      "description": "The payment method used for a cash-on-delivery parcel, as reported by the locker provider. Absent when the shipment carries no CoD payment."
     },
     "lockStatus": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "LOCKED",
       "UNLOCKED",
       null
      ],
      "example": "LOCKED",
      "description": "The current provider lock state of the parcel, when known. `LOCKED` means the consignee cannot collect the parcel (e.g. a cash-on-delivery payment is still pending); `UNLOCKED` means it can be collected. Absent when the parcel carries no lock state."
     },
     "signature": {
      "$ref": "#/components/schemas/signature",
      "deprecated": true,
      "description": "The same value as `shipmentSignature`. Sent only when the parcel has a signature. Use `shipmentSignature` instead."
     }
    },
    "required": [
     "shipmentUid",
     "lockerUid",
     "carrierParcelId",
     "dimensionsStatus",
     "shipmentStatus",
     "isFinal",
     "consignee",
     "requiresAccessibleCompartment"
    ]
   },
   "sma_error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "string",
      "description": "A message describing the error.",
      "example": "Malformed request body"
     }
    },
    "required": [
     "error"
    ]
   },
   "parcel_page": {
    "type": "object",
    "description": "A paginated list of parcels.",
    "properties": {
     "content": {
      "type": "array",
      "description": "The list of parcels for the current page.",
      "items": {
       "$ref": "#/components/schemas/parcel_response"
      }
     },
     "pageNumber": {
      "type": "integer",
      "format": "int32",
      "description": "The current page number (1-based).",
      "example": 1
     },
     "pageSize": {
      "type": "integer",
      "format": "int32",
      "description": "The number of items per page.",
      "example": 30
     },
     "isLast": {
      "type": "boolean",
      "description": "Whether this is the last page.",
      "example": true
     }
    },
    "required": [
     "content",
     "pageNumber",
     "pageSize",
     "isLast"
    ]
   },
   "parcel_lock_request": {
    "type": "object",
    "additionalProperties": false,
    "required": [
     "status"
    ],
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "LOCKED",
       "UNLOCKED"
      ],
      "example": "LOCKED",
      "description": "The lock state to apply. `LOCKED` blocks the consignee from collecting the parcel; `UNLOCKED` releases it for collection."
     },
     "reason": {
      "type": "string",
      "enum": [
       "CASH_ON_DELIVERY",
       "POLICE_HOLD",
       "OTHER"
      ],
      "example": "CASH_ON_DELIVERY",
      "description": "Why the parcel is being locked. Optional. On `LOCKED` it defaults to `CASH_ON_DELIVERY` when omitted. On `UNLOCKED` it is ignored — the parcel's original lock reason determines how it is released."
     }
    }
   },
   "MockServiceError": {
    "type": "object",
    "x-internal": true,
    "required": [
     "message"
    ],
    "properties": {
     "message": {
      "type": "string",
      "description": "Error message.",
      "example": "Missing provider_name parameter in request body"
     }
    }
   },
   "mock_parcel_event": {
    "type": "object",
    "x-internal": true,
    "description": "A Parcel Updates webhook body, unchanged. The fields below are the ones that the platform sends; see the Parcel Updates webhook for their meaning. This schema is documentation only. The mock does not check the stored body against it, and the tests check it only against sample bodies. The Parcel Updates webhook in the carrier-gateway specification is the contract.",
    "required": [
     "carrierParcelId"
    ],
    "properties": {
     "shipmentUid": {
      "type": "string",
      "example": "7c1f0f0e-9b1e-4f43-9d55-0d9f0c1a2b3c"
     },
     "lockerUid": {
      "type": "string",
      "example": "1002377838"
     },
     "carrierParcelId": {
      "type": "string",
      "example": "000123456789"
     },
     "carrierLockerId": {
      "type": [
       "string",
       "null"
      ],
      "example": "99663306"
     },
     "compartmentId": {
      "type": [
       "string",
       "null"
      ],
      "example": "A-01"
     },
     "compartmentSize": {
      "type": [
       "string",
       "null"
      ],
      "example": "MEDIUM"
     },
     "mdmLocationId": {
      "type": [
       "string",
       "null"
      ],
      "example": "123456"
     },
     "barcodeContent": {
      "type": [
       "string",
       "null"
      ],
      "example": "LBL000000018"
     },
     "shipmentType": {
      "type": "string",
      "example": "LAST_MILE"
     },
     "dimensionsStatus": {
      "type": "string",
      "example": "PARCEL_DIMENSIONS_OK"
     },
     "shipmentStatus": {
      "type": [
       "string",
       "null"
      ],
      "example": "COURIER_DELIVERED"
     },
     "isFinal": {
      "type": [
       "boolean",
       "null"
      ],
      "example": false
     },
     "accessCodes": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "consigneeCollection": {
        "type": [
         "string",
         "null"
        ],
        "example": "342156"
       },
       "consigneeCollectionCode": {
        "type": [
         "object",
         "null"
        ],
        "properties": {
         "code": {
          "type": [
           "string",
           "null"
          ],
          "example": "342156"
         },
         "validUntil": {
          "type": [
           "string",
           "null"
          ],
          "format": "date-time",
          "example": "2026-08-20T00:00:00Z"
         }
        },
        "x-internal": true
       }
      },
      "x-internal": true
     },
     "consignee": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "name": {
        "type": [
         "string",
         "null"
        ]
       },
       "email": {
        "type": [
         "string",
         "null"
        ]
       }
      },
      "x-internal": true
     },
     "events": {
      "type": [
       "array",
       "null"
      ],
      "items": {
       "type": "object",
       "properties": {
        "eventType": {
         "type": "string",
         "example": "COURIER_DELIVERED"
        },
        "timestamp": {
         "type": [
          "string",
          "null"
         ],
         "format": "date-time",
         "example": "2026-08-20T00:00:00Z"
        }
       },
       "x-internal": true
      },
      "x-internal": true
     },
     "allocationType": {
      "type": [
       "string",
       "null"
      ],
      "example": "HARD_RESERVATION"
     },
     "carrierName": {
      "type": [
       "string",
       "null"
      ],
      "example": "GLS_NXT"
     },
     "providerName": {
      "type": [
       "string",
       "null"
      ],
      "example": "KEBA"
     },
     "providerLockerId": {
      "type": [
       "string",
       "null"
      ],
      "example": "99663306"
     },
     "shipmentSignature": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "imageBase64": {
        "type": [
         "string",
         "null"
        ]
       },
       "format": {
        "type": [
         "string",
         "null"
        ]
       }
      },
      "x-internal": true
     },
     "requiresAccessibleCompartment": {
      "type": [
       "boolean",
       "null"
      ],
      "example": false
     },
     "labelType": {
      "type": [
       "string",
       "null"
      ],
      "example": "LABELED"
     },
     "referenceCode": {
      "type": [
       "string",
       "null"
      ],
      "example": "LBL-000123456789"
     },
     "secondaryShipmentId": {
      "type": [
       "string",
       "null"
      ],
      "example": "EXP-CODE-0001"
     },
     "eventTimestamp": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time",
      "example": "2026-08-20T00:00:00Z"
     }
    }
   },
   "mock_locker_event": {
    "type": "object",
    "x-internal": true,
    "description": "A Locker Updates webhook body, unchanged. The fields below are the ones that the platform sends; see the Locker Updates webhook for their meaning. This schema is documentation only. The mock does not check the stored body against it, and the tests check it only against sample bodies. The Locker Updates webhook in the carrier-gateway specification is the contract.",
    "required": [
     "eventTimestamp",
     "uid"
    ],
    "properties": {
     "eventTimestamp": {
      "type": "string",
      "format": "date-time",
      "example": "2026-08-20T00:00:00Z"
     },
     "uid": {
      "type": "string",
      "example": "1002377838"
     },
     "carrier": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "lockerName": {
        "type": "string",
        "example": "Test Locker 01"
       },
       "lockerId": {
        "type": "string",
        "example": "99663306"
       },
       "activationDate": {
        "type": [
         "string",
         "null"
        ],
        "format": "date-time",
        "example": "2026-08-20T00:00:00Z"
       },
       "status": {
        "type": "string",
        "example": "ACTIVE"
       }
      },
      "x-internal": true
     },
     "provider": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "name": {
        "type": "string",
        "example": "KEBA"
       },
       "lockerModel": {
        "type": "string",
        "example": "Model 1"
       },
       "lockerVersion": {
        "type": "string",
        "example": "v2.1"
       },
       "lockerName": {
        "type": [
         "string",
         "null"
        ]
       },
       "lockerUid": {
        "type": [
         "string",
         "null"
        ],
        "example": "99663306"
       },
       "status": {
        "type": "string",
        "example": "ACTIVE"
       }
      },
      "x-internal": true
     },
     "location": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "street": {
        "type": "string"
       },
       "streetNumber": {
        "type": "string"
       },
       "postalCode": {
        "type": "string"
       },
       "city": {
        "type": "string"
       },
       "lon": {
        "type": "number",
        "format": "double"
       },
       "lat": {
        "type": "number",
        "format": "double"
       },
       "countryCode": {
        "type": "string",
        "example": "DE"
       },
       "type": {
        "type": [
         "string",
         "null"
        ],
        "example": "indoor"
       }
      },
      "x-internal": true
     },
     "features": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "hasScreen": {
        "type": [
         "boolean",
         "null"
        ]
       },
       "hasPinPad": {
        "type": [
         "boolean",
         "null"
        ]
       },
       "hasPinBarcodeReader": {
        "type": [
         "boolean",
         "null"
        ]
       }
      },
      "x-internal": true
     },
     "openingHours": {
      "type": [
       "object",
       "null"
      ],
      "description": "Same structure as `openingHours` in the Locker Updates webhook."
     },
     "metadata": {
      "type": [
       "array",
       "null"
      ],
      "items": {
       "type": "object",
       "properties": {
        "key": {
         "type": [
          "string",
          "null"
         ]
        },
        "value": {
         "type": [
          "string",
          "null"
         ]
        }
       },
       "x-internal": true
      },
      "x-internal": true
     },
     "ownedByCarrier": {
      "type": [
       "string",
       "null"
      ],
      "example": "GLS"
     },
     "compartmentTypes": {
      "type": [
       "array",
       "null"
      ],
      "items": {
       "type": "object",
       "properties": {
        "size": {
         "type": "string",
         "example": "MEDIUM"
        },
        "count": {
         "type": "integer",
         "example": 4
        },
        "width": {
         "type": "integer",
         "example": 400
        },
        "height": {
         "type": "integer",
         "example": 400
        },
        "length": {
         "type": "integer",
         "example": 600
        }
       },
       "x-internal": true
      },
      "x-internal": true
     }
    }
   },
   "mock_collection_event": {
    "type": "object",
    "x-internal": true,
    "description": "A Collection Notification webhook body, unchanged. The fields below are the ones that the platform sends; see the Collection Notification webhook for their meaning. This schema is documentation only. The mock does not check the stored body against it, and the tests check it only against sample bodies. The Collection Notification webhook in the carrier-gateway specification is the contract.",
    "required": [
     "lockerUid"
    ],
    "properties": {
     "eventTimestamp": {
      "type": "string",
      "format": "date-time",
      "example": "2026-08-20T00:00:00Z"
     },
     "lockerUid": {
      "type": "string",
      "example": "1002377838"
     },
     "carrierLockerId": {
      "type": [
       "string",
       "null"
      ],
      "example": "99663306"
     },
     "courierAccessCode": {
      "type": [
       "string",
       "null"
      ],
      "example": "342156"
     },
     "parcels": {
      "type": [
       "array",
       "null"
      ],
      "items": {
       "type": "object",
       "properties": {
        "carrierParcelId": {
         "type": "string",
         "example": "000123456789"
        }
       },
       "x-internal": true
      },
      "x-internal": true
     }
    }
   },
   "webhook_locker_carrier": {
    "allOf": [
     {
      "$ref": "#/components/schemas/carrier"
     },
     {
      "type": "object",
      "required": [
       "status"
      ],
      "properties": {
       "status": {
        "type": "string",
        "description": "The status of the locker for the carrier. carrier-gateway sends `INITIAL` and `PLANNED` as `INACTIVE`.\n",
        "enum": [
         "ACTIVE",
         "INACTIVE",
         "MAINTENANCE",
         "DECOMMISSIONED"
        ],
        "example": "ACTIVE"
       }
      }
     }
    ]
   },
   "webhook_locker_provider": {
    "allOf": [
     {
      "$ref": "#/components/schemas/provider"
     },
     {
      "type": "object",
      "required": [
       "lockerUid",
       "status"
      ],
      "properties": {
       "lockerName": {
        "type": "string",
        "description": "The name of the locker on the Provider's system.",
        "example": "BLOQ-Berlin-12045-001"
       },
       "lockerUid": {
        "type": "string",
        "description": "The unique identifier of the locker on the Provider's system.",
        "example": "PROVIDER_LOCKER_ABC123"
       },
       "status": {
        "type": "string",
        "description": "The status of the locker returned by the provider. carrier-gateway sends `PLANNED` as `INACTIVE`.",
        "enum": [
         "ACTIVE",
         "INACTIVE"
        ],
        "example": "ACTIVE"
       }
      }
     }
    ]
   },
   "webhook_location": {
    "type": "object",
    "description": "Details about the geographical location of the locker.",
    "required": [
     "street",
     "streetNumber",
     "postalCode",
     "city",
     "lon",
     "lat",
     "countryCode"
    ],
    "properties": {
     "street": {
      "type": "string",
      "description": "The street name where the locker is located.",
      "example": "Main Street"
     },
     "streetNumber": {
      "type": "string",
      "description": "The street number of the locker location. Empty when the locker has no street number.",
      "example": "1"
     },
     "postalCode": {
      "type": "string",
      "description": "The postal code of the locker location.",
      "example": "90210"
     },
     "city": {
      "type": "string",
      "description": "The city where the locker is located.",
      "example": "Berlin"
     },
     "lon": {
      "type": "number",
      "format": "double",
      "description": "The longitude coordinate of the locker location.",
      "example": -118.2437
     },
     "lat": {
      "type": "number",
      "format": "double",
      "description": "The latitude coordinate of the locker location.",
      "example": 34.0522
     },
     "countryCode": {
      "type": "string",
      "description": "The ISO 3166-1 alpha-2 country code for the locker location.",
      "example": "DE"
     },
     "locationType": {
      "type": "string",
      "description": "Whether the locker is indoors or outdoors, for example `indoor` or `outdoor`. Absent when unspecified.",
      "example": "indoor"
     },
     "locationSubtype": {
      "type": "string",
      "description": "The kind of place where the locker is, for example `GAS_STATION` or `RETAIL_SUPERMARKETS`. Absent when unspecified.",
      "example": "GAS_STATION"
     }
    }
   },
   "webhook_locker_owner": {
    "type": "object",
    "description": "The owner of the locker. Absent when the platform has no owner for the locker.",
    "required": [
     "name",
     "type"
    ],
    "properties": {
     "name": {
      "type": "string",
      "description": "The name of the owner, a carrier or a locker provider.",
      "example": "GLS"
     },
     "type": {
      "type": "string",
      "description": "Whether the owner is a carrier or a locker provider.",
      "enum": [
       "CARRIER",
       "PROVIDER"
      ],
      "example": "CARRIER"
     }
    }
   },
   "webhook_update_request": {
    "type": "object",
    "description": "The locker data that carrier-gateway sends when a locker of the carrier is created or changes.\ncarrier-gateway omits an optional field when it has no value; it never sends `null`.\n",
    "required": [
     "uid",
     "carrier",
     "provider",
     "location",
     "features",
     "metadata",
     "compartmentTypes",
     "eventTimestamp"
    ],
    "properties": {
     "uid": {
      "type": "string",
      "description": "The internal unique identifier assigned to the locker.",
      "example": "1002377838"
     },
     "carrier": {
      "$ref": "#/components/schemas/webhook_locker_carrier"
     },
     "provider": {
      "$ref": "#/components/schemas/webhook_locker_provider"
     },
     "location": {
      "$ref": "#/components/schemas/webhook_location"
     },
     "features": {
      "$ref": "#/components/schemas/features"
     },
     "metadata": {
      "type": "array",
      "description": "Additional metadata associated with the locker.",
      "items": {
       "$ref": "#/components/schemas/metadata"
      }
     },
     "compartmentTypes": {
      "type": "array",
      "description": "A list of different compartment types available in the locker.",
      "items": {
       "$ref": "#/components/schemas/compartment"
      }
     },
     "eventTimestamp": {
      "type": "string",
      "format": "date-time",
      "example": "2025-08-20T00:00:00Z",
      "description": "The timestamp of the locker status update."
     },
     "openingHours": {
      "$ref": "#/components/schemas/opening_hours"
     },
     "owner": {
      "$ref": "#/components/schemas/webhook_locker_owner"
     }
    }
   },
   "parcel_event": {
    "type": "object",
    "required": [
     "shipmentUid",
     "lockerUid",
     "carrierParcelId",
     "carrierLockerId",
     "carrierName",
     "shipmentType",
     "shipmentStatus",
     "dimensionsStatus",
     "events",
     "eventTimestamp"
    ],
    "properties": {
     "shipmentUid": {
      "type": "string",
      "example": "anyParcelId123",
      "description": "The unique identifier of the parcel shipment in the GLS/NXT Platform"
     },
     "lockerUid": {
      "type": "string",
      "example": "anyLockerId123",
      "description": "The unique identifier of the locker in the GLS/NXT Platform"
     },
     "carrierParcelId": {
      "type": "string",
      "example": "anyCarrierParcelId123",
      "description": "The identifier of the parcel in the carrier's system"
     },
     "carrierLockerId": {
      "type": "string",
      "example": "Locker1",
      "description": "The identifier of the locker in the carrier's system"
     },
     "compartmentId": {
      "type": [
       "string",
       "null"
      ],
      "example": "A-01",
      "description": "The identifier of the compartment assigned to the parcel"
     },
     "compartmentSize": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "XXSMALL",
       "XSMALL",
       "SMALL",
       "XMEDIUM",
       "MEDIUM",
       "LARGE",
       "XLARGE",
       "XXLARGE",
       "ULARGE",
       "UULARGE",
       null
      ],
      "example": "MEDIUM",
      "description": "The size of the compartment assigned to the parcel"
     },
     "mdmLocationId": {
      "type": [
       "string",
       "null"
      ],
      "example": "123456",
      "description": "Specific to certain carriers only. The MDM location identifier associated with the parcel locker"
     },
     "barcodeContent": {
      "type": [
       "string",
       "null"
      ],
      "example": "LBL000000018",
      "description": "Specific to certain carriers only. The barcode content associated with the parcel"
     },
     "shipmentType": {
      "$ref": "#/components/schemas/shipment_type"
     },
     "dimensionsStatus": {
      "$ref": "#/components/schemas/dimensions_status"
     },
     "shipmentStatus": {
      "$ref": "#/components/schemas/shipment_status"
     },
     "accessCodes": {
      "$ref": "#/components/schemas/access_codes"
     },
     "consignee": {
      "$ref": "#/components/schemas/consignee"
     },
     "events": {
      "$ref": "#/components/schemas/parcel_events"
     },
     "allocationType": {
      "$ref": "#/components/schemas/allocation_type"
     },
     "carrierName": {
      "type": "string",
      "example": "GLS_DE",
      "description": "The name of the carrier"
     },
     "providerName": {
      "type": [
       "string",
       "null"
      ],
      "example": "LOCKY_PT",
      "description": "The name of the locker network provider"
     },
     "providerLockerId": {
      "type": [
       "string",
       "null"
      ],
      "example": "1178",
      "description": "The identifier of the locker in the provider's system"
     },
     "signature": {
      "type": "string",
      "deprecated": true,
      "example": "imageBase64StringHere",
      "description": "The Base64-encoded signature image. Deprecated, use `shipmentSignature.imageBase64`. Absent when there is no signature."
     },
     "shipmentSignature": {
      "$ref": "#/components/schemas/signature"
     },
     "requireEasyAccess": {
      "type": "boolean",
      "example": true,
      "description": "Whether the parcel needs an accessible compartment. Absent when the platform did not say."
     },
     "labelType": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "LABELLESS",
       "LABELED",
       null
      ],
      "example": "LABELLESS",
      "description": "Label mode for the shipment. `LABELLESS` means no printed label is used and `LABELED` means a printed label is used."
     },
     "referenceCode": {
      "type": [
       "string",
       "null"
      ],
      "example": "LBL000000018",
      "description": "Reference code scanned by driver during pickup of the labelless parcel. This field is only relevant for `LABELLESS` shipments."
     },
     "secondaryShipmentId": {
      "type": [
       "string",
       "null"
      ],
      "example": "EXP-CODE-0001",
      "description": "A secondary identifier for the shipment, separate from `carrierParcelId`."
     },
     "lockStatus": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "LOCKED",
       "UNLOCKED",
       null
      ],
      "example": "LOCKED",
      "description": "The current provider lock state of the parcel, when known. `LOCKED` means the consignee cannot collect the parcel (e.g. a cash-on-delivery payment is still pending); `UNLOCKED` means it can be collected. Absent when the parcel carries no lock state."
     },
     "codAmount": {
      "type": [
       "integer",
       "null"
      ],
      "format": "int64",
      "example": 2450,
      "description": "The cash-on-delivery amount to collect from the consignee, in the currency's minor units (e.g. cents). Absent for parcels without cash-on-delivery."
     },
     "codCurrency": {
      "type": [
       "string",
       "null"
      ],
      "example": "EUR",
      "description": "ISO 4217 currency code for `codAmount`. Absent when `codAmount` is absent."
     },
     "paymentType": {
      "type": [
       "string",
       "null"
      ],
      "enum": [
       "CARD",
       "FLIK",
       null
      ],
      "example": "CARD",
      "description": "The method the consignee paid a cash-on-delivery parcel with, as reported by the locker provider. The value set is country-specific: Slovenia (`GLS_SI`) is the only country live with cash-on-delivery today and reports `CARD` or `FLIK`, and the enum is extended as further countries are enabled. Absent for parcels without cash-on-delivery, before the payment is made, and when the provider reported no method or one outside the agreed set."
     },
     "eventTimestamp": {
      "type": "string",
      "format": "date-time",
      "example": "2025-08-20T00:00:00Z",
      "description": "The timestamp of the parcel update"
     }
    }
   },
   "collection_events": {
    "type": "object",
    "required": [
     "eventTimestamp",
     "lockerUid",
     "carrierLockerId",
     "parcels"
    ],
    "properties": {
     "eventTimestamp": {
      "type": "string",
      "format": "date-time",
      "example": "2025-08-20T00:00:00Z",
      "description": "The timestamp of the collection event"
     },
     "lockerUid": {
      "type": "string",
      "description": "The unique identifier of the locker in the GLS/NXT Platform",
      "example": "8979879823"
     },
     "carrierLockerId": {
      "type": "string",
      "description": "The unique identifier of the locker in the Carrier's system",
      "example": "GHX1234"
     },
     "courierAccessCode": {
      "type": [
       "string",
       "null"
      ],
      "description": "Access code for the courier to collect parcels from locker. Access code rotates daily.",
      "example": "342156"
     },
     "parcels": {
      "type": "array",
      "items": {
       "type": "object",
       "required": [
        "carrierParcelId"
       ],
       "properties": {
        "carrierParcelId": {
         "type": "string",
         "description": "The identifier of the parcel in the carrier's system",
         "example": "1234212321"
        }
       }
      }
     }
    }
   }
  },
  "responses": {
   "200": {
    "description": "Return a 200 status to indicate that the data was received successfully."
   },
   "401": {
    "description": "Return a 401 status to indicate that the POST was unauthorized."
   },
   "500": {
    "description": "Return a 500 status to indicate that the POST was unsuccessfully processed."
   },
   "response_400": {
    "description": "Bad request due to invalid input.",
    "content": {
     "application/json": {
      "schema": {
       "type": "object",
       "properties": {
        "errorCode": {
         "type": "string",
         "description": "A code representing the type of error.",
         "example": "Bad Request"
        },
        "message": {
         "type": "string",
         "description": "A message describing the error.",
         "example": "ids parameter is required"
        }
       },
       "required": [
        "errorCode",
        "message"
       ]
      }
     }
    }
   },
   "gateway_401": {
    "description": "The `X-API-Key` header is missing or not valid. The API gateway sends this response.",
    "x-ooh-gateway-response": true,
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/gateway_error"
      },
      "example": {
       "message": "No API key found in request",
       "request_id": "7ffd2e0e5888950b8932023263c33c26"
      }
     }
    }
   },
   "response_500": {
    "description": "The server encountered an internal error.",
    "content": {
     "application/json": {
      "schema": {
       "type": "object",
       "properties": {
        "errorCode": {
         "type": "string",
         "description": "A code representing the type of error.",
         "example": "Internal Server Error"
        },
        "message": {
         "type": "string",
         "description": "A message describing the error.",
         "example": "The server encountered an internal error"
        }
       }
      }
     }
    }
   },
   "response_404": {
    "description": "The requested resource was not found.",
    "content": {
     "application/json": {
      "schema": {
       "type": "object",
       "properties": {
        "errorCode": {
         "type": "string",
         "description": "A code representing the type of error.",
         "example": "Not Found"
        },
        "message": {
         "type": "string",
         "description": "A message describing the error.",
         "example": "Locker group not found"
        }
       },
       "required": [
        "errorCode",
        "message"
       ]
      }
     }
    }
   },
   "parcel_input_200": {
    "description": "Parcel event published successfully",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/input_data_response"
      }
     }
    }
   },
   "parcel_input_400": {
    "description": "The request body could not be parsed, or a field has a value the platform does not accept.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/parcel_input_error"
      },
      "example": {
       "error": "Failed to parse request"
      }
     }
    }
   },
   "parcel_input_500": {
    "description": "The server encountered an internal error.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/parcel_input_error"
      },
      "example": {
       "error": "Internal Server Error"
      }
     }
    }
   },
   "sma_400": {
    "description": "The request is not valid. A required query parameter is missing or blank, a parameter has a value the platform does not accept, or the request body cannot be parsed.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/sma_error"
      },
      "example": {
       "error": "ids parameter is required and should not be blank"
      }
     }
    }
   },
   "sma_500": {
    "description": "The server encountered an internal error.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/sma_error"
      },
      "example": {
       "error": "Internal Server Error"
      }
     }
    }
   },
   "sma_422": {
    "description": "The request is valid, but the platform cannot do it. The requested page is too deep, or parcel locking is not enabled for the carrier.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/sma_error"
      },
      "example": {
       "error": "Parcel lock is not enabled for carrier GLS_AT"
      }
     }
    }
   },
   "sma_provider_error": {
    "description": "The parcel locker provider refused or failed the request. SMA returns the provider's HTTP status (for example 502 or 503) with this body.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/sma_error"
      },
      "example": {
       "error": "Not possible to set parcel lock"
      }
     }
    }
   },
   "sma_404": {
    "description": "The carrier has no open parcel with this ID.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/sma_error"
      },
      "example": {
       "error": "Unable to find shipment [parcelId=1234567890, shipmentId=null]"
      }
     }
    }
   },
   "sma_409": {
    "description": "The parcel has a status that does not allow cancellation, for example because it is already delivered.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/sma_error"
      },
      "example": {
       "error": "Not possible to cancel shipment with status COURIER_DELIVERED."
      }
     }
    }
   },
   "mock_trigger_400": {
    "description": "The request is not valid. For example, the body is not JSON, a required field is missing, or the provider does not support the event. The mock does not send an event.",
    "x-internal": true,
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/MockServiceError"
      }
     }
    }
   },
   "mock_event_query_400": {
    "description": "The ID in the path is empty, for example `GET /parcel/events/`.\nNo event-query route matches that path, so the request reaches the trigger API, which sends this response. The message does not describe the cause. Send a non-empty ID.",
    "x-internal": true,
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/MockServiceError"
      },
      "example": {
       "message": "Invalid JSON in request body"
      }
     }
    }
   },
   "mock_event_query_500": {
    "description": "The mock cannot read its event store. Try again later. The body is a JSON string.",
    "x-internal": true,
    "content": {
     "application/json": {
      "schema": {
       "type": "string",
       "x-internal": true
      },
      "example": "Failed to retrieve locker events"
     }
    }
   }
  }
 }
}
