A tender (gara d’appalto) is the master configuration entity that defines which delivery drivers serve which geographic areas and at what costs. Before pn-paper-channel can route paper notifications, at least one tender must be active.
Lifecycle states
Every tender moves through these states:
- DRAFT — The tender has been created and can be edited. Delivery drivers and costs can be added.
- ACTIVE — The tender is in use. The service uses its delivery drivers and cost tables to route and price notifications.
- EXPIRED — The tender’s
endDate has passed or another tender was activated in its place.
Activating a new tender replaces the currently active one. Make sure the new tender is fully configured with drivers and costs before activating it.
Creating a tender
Use the POST /paper-channel-bo/v1/tender endpoint. You need the tender-write permission.
curl -X POST https://<host>/paper-channel-bo/v1/tender \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" \
-d '{
"name": "Gara 2025-Q1",
"startDate": "2025-01-01",
"endDate": "2025-03-31"
}'
The code field is optional. If omitted, the server generates one.
Response schema (TenderCreateResponseDTO):
{
"tender": {
"code": "TENDER-001",
"name": "Gara 2025-Q1",
"startDate": "2025-01-01",
"endDate": "2025-03-31",
"status": "DRAFT"
}
}
Record the code value — you need it for all subsequent operations on this tender.
Adding delivery drivers
Use POST /paper-channel-bo/v1/delivery-driver/{tenderCode} to associate a delivery driver with the tender. You need the tender-write permission.
curl -X POST https://<host>/paper-channel-bo/v1/delivery-driver/TENDER-001 \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" \
-d '{
"taxId": "12345678901",
"businessName": "Recapitisti S.p.A.",
"fiscalCode": "12345678901",
"pec": "[email protected]",
"phoneNumber": "+390612345678",
"registeredOffice": "Via Roma 1, 00100 Roma",
"fsu": false
}'
Set "fsu": true if this driver is the Fornitore Servizio Universale (FSU) for the tender.
To retrieve all drivers for a tender:
curl -X GET "https://<host>/paper-channel-bo/v1/deliveries-drivers/TENDER-001?page=0&size=20" \
-H "x-api-key: <your-api-key>"
To retrieve only the FSU:
curl -X GET https://<host>/paper-channel-bo/v1/deliveries-drivers/TENDER-001/fsu \
-H "x-api-key: <your-api-key>"
Adding costs
Use POST /paper-channel-bo/v1/{tenderCode}/delivery-driver/{deliveryDriverId}/cost to add a cost entry for a driver. You need the tender-write permission.
Each cost entry covers one product type and a set of geographic keys (CAP codes or international zones). Prices are given in euro for different weight ranges (grams).
curl -X POST \
https://<host>/paper-channel-bo/v1/TENDER-001/delivery-driver/<deliveryDriverId>/cost \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" \
-d '{
"productType": "AR",
"cap": ["00100", "00118"],
"price": 1.20,
"price50": 1.30,
"price100": 1.50,
"price250": 1.80,
"price350": 2.00,
"price1000": 2.50,
"price2000": 3.00,
"priceAdditional": 0.10
}'
For international deliveries, use "zone" instead of "cap":
curl -X POST \
https://<host>/paper-channel-bo/v1/TENDER-001/delivery-driver/<deliveryDriverId>/cost \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" \
-d '{
"productType": "RS",
"zone": "ZONE_1",
"price": 2.50,
"priceAdditional": 0.25
}'
To view all costs for a driver in a tender:
curl -X GET \
"https://<host>/paper-channel-bo/v1/TENDER-001/delivery-driver/<deliveryDriverId>/get-cost?page=0&size=50" \
-H "x-api-key: <your-api-key>"
Activating a tender
Once the tender is fully configured, activate it with PUT /paper-channel-bo/v1/tender/{tenderCode}. You need the tender-write permission.
curl -X PUT https://<host>/paper-channel-bo/v1/tender/TENDER-001 \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" \
-d '"ACTIVE"'
The request body is a Status enum value: "ACTIVE", "DRAFT", or "EXPIRED".
Activating a tender while another one is already active will replace the active tender. Verify that all drivers and costs are correct before sending this request.
Downloading tender data
The GET /paper-channel-bo/v1/delivery-tender/file-download endpoint returns a presigned download URL or the file content for the tender data export. You need the tender-read permission.
curl -X GET \
"https://<host>/paper-channel-bo/v1/delivery-tender/file-download?tenderCode=TENDER-001&uuid=<file-uuid>" \
-H "x-api-key: <your-api-key>"
The response is an InfoDownloadDTO with fields:
| Field | Type | Description |
|---|
uuid | string | File identifier |
status | UPLOADING | UPLOADED | Upload status |
data | byte (base64) | File content when status is UPLOADED |
retryAfter | integer | Milliseconds to wait before polling again when status is UPLOADING |
Using the tenderAPILambda for read operations
For read-only access to tender data outside the Back-Office API, invoke the pn-paper-channel-tenderAPILambda directly. The Lambda reads from DynamoDB and supports five operations.
The Lambda function name follows the pattern {ProjectName}-paper-channel-TenderAPI (e.g., pn-paper-channel-TenderAPI in production).
List tenders
aws lambda invoke \
--function-name pn-paper-channel-tenderAPILambda \
--payload '{
"operation": "GET_TENDERS",
"page": 0,
"size": 20,
"from": "2025-01-01T00:00:00.000Z",
"to": "2025-12-31T23:59:59.999Z"
}' \
response.json
Omit from and to to return all tenders. The active boolean field in each result indicates whether the tender is currently active.
Get the active tender
aws lambda invoke \
--function-name pn-paper-channel-tenderAPILambda \
--payload '{"operation": "GET_TENDER_ACTIVE"}' \
response.json
Returns 404 if no tender is currently active.
Get costs for a tender
aws lambda invoke \
--function-name pn-paper-channel-tenderAPILambda \
--payload '{
"operation": "GET_COSTS",
"tenderId": "<tenderId>",
"product": "AR",
"lot": "LOT-1",
"zone": "ZONE_1",
"deliveryDriverId": "<driverId>"
}' \
response.json
All filter fields (product, lot, zone, deliveryDriverId) are optional.
Get a specific cost by geokey
aws lambda invoke \
--function-name pn-paper-channel-tenderAPILambda \
--payload '{
"operation": "GET_COST",
"tenderId": "<tenderId>",
"product": "AR",
"geokey": "00100"
}' \
response.json
List geokey versions
aws lambda invoke \
--function-name pn-paper-channel-tenderAPILambda \
--payload '{
"operation": "GET_GEOKEY",
"tenderId": "<tenderId>",
"product": "AR",
"geokey": "00100"
}' \
response.json
List all delivery drivers
aws lambda invoke \
--function-name pn-paper-channel-tenderAPILambda \
--payload '{"operation": "GET_DELIVERY_DRIVERS"}' \
response.json
Deleting tenders and drivers
You can delete a tender that is still in DRAFT state:
curl -X DELETE https://<host>/paper-channel-bo/v1/tender/TENDER-001 \
-H "x-api-key: <your-api-key>"
To remove a delivery driver from a tender:
curl -X DELETE \
https://<host>/paper-channel-bo/v1/TENDER-001/delivery-driver/<deliveryDriverId> \
-H "x-api-key: <your-api-key>"
To remove a specific cost entry:
curl -X DELETE \
https://<host>/paper-channel-bo/v1/TENDER-001/delivery-driver/<deliveryDriverId>/cost/<uuid> \
-H "x-api-key: <your-api-key>"
All write endpoints require the tender-write API permission. All read endpoints require tender-read.