External API Documentation
Overview
This External API is built using FastAPI and deployed on Google Cloud Platform with API Gateway for security and traffic management. The API provides secure access to our services through a token-based authentication system.
Architecture
- Backend: FastAPI application running on Google Cloud Run
- Gateway: Google Cloud API Gateway for request routing and security
- Authentication: JWT-based token system with Basic Auth for initial authentication
- Deployment: Automated CI/CD pipeline using Google Cloud Build
Base URL
API Authentication
How to Get and Use Your Token
To access most of our API's features, you'll need to authenticate. This process involves getting a token that you'll then use for all your subsequent requests. Here's how it works:
1. Getting Your Authentication Token
You'll start by sending a GET request to the /authentication endpoint. You must include an Authorization header in every request. The header should use the Basic scheme, followed by a base64-encoded string of your email:password.
Format:
where base64(email:password) is the base64 encoded email:password.
Example:
# If your email is "user@example.com" and password is "mypassword"
# The base64 encoding of "user@example.com:mypassword" is "dXNlckBleGFtcGxlLmNvbTpteXBhc3N3b3Jk"
curl -X GET "https://external-api-gateway-525b4eqm.ew.gateway.dev/authentication" \
-H "Authorization: Basic dXNlckBleGFtcGxlLmNvbTpteXBhc3N3b3Jk"
If your email and password are correct, the API will respond with a JSON containing:
{
"message": "Authentication successful",
"email": "youremail@example.com",
"idToken": "yourtokenid",
"expiresIn": "expiration (in seconds)"
}
yourtokenid is your unique authorization token. Your token expires in 60 minutes starting the moment you receive it.
2. Using Your Token for Subsequent Requests
Once you have your tokenid, you must include it in the header of every request you make to other protected API endpoints. The header should be named Authorization, and its value must start with Bearer followed by your tokenid.
For instance, if your tokenid is yourtokenid, your Authorization header will look like this:
Just replace yourtokenid with the actual token you received from the /authentication endpoint. This tells the API that you are authorized to access the requested resources.
Example:
curl -X GET "https://external-api-gateway-525b4eqm.ew.gateway.dev/orders" \
-H "Authorization: Bearer yourtokenid"
API Endpoints
Authentication Endpoint
| Method | Endpoint | Description | Authentication |
|---|---|---|---|
GET |
/authentication |
Get authentication token | Basic Auth |
Protected Endpoints
All other endpoints require Bearer token authentication as described above.
| Method | Endpoint | Description | Authentication |
|---|---|---|---|
GET |
/orders |
Retrieve most recent orders (limited to 100 most recent updates) | Bearer Token |
GET |
/orders/{order_id} |
Retrieve historical process of a specific order | Bearer Token |
POST |
/createDelivery |
Import multiple orders into the system | Bearer Token |
PUT |
/updateDelivery |
Update address information for an existing order | Bearer Token |
POST |
/create_invoices |
Import one or more invoices with multiple parcels each | Bearer Token |
GET |
/invoices/{invoice_number} |
Get all order IDs associated with an invoice | Bearer Token |
PUT |
/update_invoice |
Update the delivery address for all parcels of an invoice | Bearer Token |
PUT |
/cancel_invoice |
Cancel or uncancel all parcels of an invoice | Bearer Token |
Detailed Endpoint Documentation
GET /orders
Retrieves the most recent updates of orders (limited to the 100 most recent updates).
Query Parameters:
- order_date (optional): Filter by order date (format: YYYY-MM-DD)
- order_status (optional): Filter by order status
Example Request:
curl -X GET "https://external-api-gateway-525b4eqm.ew.gateway.dev/orders?order_date=2024-06-25&order_status=pending" \
-H "Authorization: Bearer yourtokenid"
GET /orders/{order_id}
Retrieves the historical process of a specific order.
Path Parameters:
- order_id (required): The unique identifier of the order
Example Request:
curl -X GET "https://external-api-gateway-525b4eqm.ew.gateway.dev/orders/ORD001" \
-H "Authorization: Bearer yourtokenid"
POST /createDelivery
Import multiple orders into the system.
Request Body: Array of order objects with the following structure:
[
{
"customerInfo": {
"clientId": "C123",
"clientName": "Pedro",
"clientPhone": "+351912345678",
"clientEmail": "Pedro@example.com"
},
"orderInfo": {
"orderId": "ORD001",
"addressLine": "Rua das Flores, 123",
"country": "Portugal",
"locality": "Lisboa",
"postalCode": "1000-001",
"city": "Lisboa",
"streetNumber": "123",
"houseNumber": "1",
"lat": 38.7169,
"lon": -9.1399,
"orderDate": "2024-06-24",
"deliveryDate": "2024-06-25",
"totalVolume": 0.1,
"totalWeight": 1.5,
"orderDimensions": {
"length": 0.5,
"width": 0.4,
"height": 0.5
}
},
"slot": {
"slotFrom": "10:00",
"slotTo": "12:00"
},
"payment": {
"paymentBoolean": true,
"value": 9.99,
"paymentType": "card"
}
}
]
Response:
{
"code": "ORDERS_IMPORTED",
"message": {
"pt": "Encomendas importadas com sucesso.",
"en": "Orders have been imported."
},
"results": {
"successCount": 1,
"failedOrders": []
}
}
PUT /updateDelivery
Update address information for an existing order.
Request Body:
{
"orderId": "ORD001",
"addressLine": "Avenida da Liberdade 100",
"country": "Portugal",
"locality": "Lisboa",
"postalCode": "1250-145",
"city": "Lisboa",
"streetNumber": "100",
"houseNumber": "5"
}
Invoice Endpoints
The invoice flow allows importing shipments structured as invoices, where one invoice may contain multiple parcels. Each parcel within an invoice shares the same recipient, address and delivery date. The order IDs (barcodes) are generated automatically — see Barcode Format for details.
POST /create_invoices
Import one or more invoices. Each invoice may contain multiple parcels. The orderId / barcode for each parcel is generated automatically.
Request Body:
Array of InvoiceModel objects.
[
{
"invoiceNumber": "INV-1001",
"deliveryDate": "2024-06-25",
"customerInfo": {
"clientName": "Maria Silva",
"clientPhone": "+351987654321",
"clientEmail": "email@gmail.com"
},
"address": {
"addressLine": "Avenida da Liberdade 200",
"country": "Portugal",
"locality": "Lisboa",
"postalCode": "1250-145",
"streetNumber": "200",
"streetName": "Avenida da Liberdade",
"houseNumber": "10",
"lat": 38.717,
"lon": -9.14,
"addressNotes": ""
},
"orders": [
{
"size": 2,
"totalVolume": 0.2,
"totalWeight": 3.0,
"orderDimensions": { "length": 0.6, "width": 0.5, "height": 0.7 },
"lot": "BATCH-43",
"serviceType": "delivery",
"slot": { "slotFrom": "14:00", "slotTo": "16:00" },
"payment": { "paymentBoolean": true, "value": 19.99, "paymentType": "card" },
"generateLabel": false
},
{
"size": 1,
"totalVolume": 0.1,
"totalWeight": 1.5,
"orderDimensions": { "length": 0.5, "width": 0.4, "height": 0.5 },
"lot": "BATCH-43",
"serviceType": "delivery",
"slot": { "slotFrom": "14:00", "slotTo": "16:00" },
"payment": { "paymentBoolean": true, "value": 9.99, "paymentType": "card" },
"generateLabel": false
}
]
}
]
Response:
{
"code": "ORDERS_IMPORTED",
"message": {
"pt": "Encomendas importadas com sucesso.",
"en": "Orders have been imported."
},
"results": {
"successCount": 2,
"failedOrders": []
}
}
GET /invoices/{invoice_number}
Returns all order IDs associated with the given invoice number.
Path Parameters:
- invoice_number (required): The invoice identifier
Response:
Error (404):
PUT /update_invoice
Updates the delivery address for every parcel associated with the given invoice number.
Request Body:
{
"invoiceNumber": "INV-1001",
"addressLine": "Rua Nova 10",
"postalCode": "1000-001",
"latitude": 38.717,
"longitude": -9.14,
"addressNotes": "Ring bell 2",
"generateLabel": false
}
Response:
{
"invoiceNumber": "INV-1001",
"successCount": 2,
"failedCount": 0,
"results": [
{ "orderId": "PT000010000001018", "success": true, "response": {} },
{ "orderId": "PT000010000001026", "success": true, "response": {} }
]
}
PUT /cancel_invoice
Cancels or uncancels every parcel associated with the given invoice number. Set cancel to false to reactivate a previously cancelled invoice.
Request Body:
Response:
{
"code": "INVOICE_CANCELLED",
"message": "Invoice INV-1001 cancelled: 2/2 parcel(s) updated",
"successCount": 2,
"failedCount": 0,
"results": [
{ "orderId": "PT000010000001018", "success": true, "detail": null },
{ "orderId": "PT000010000001026", "success": true, "detail": null }
]
}
Data Models
CustomerInfo
clientName(required): Client's nameclientPhone(optional): Phone number with country codeclientEmail(optional): Email address
OrderInfo
multiDeliverId(optional): Bundle identifier for multiple ordersorderId(required): Order identifieraddressLine(optional): Full address linecountry(required): Country namelocality(required): City/localitypostalCode(required): Postal codecity(required): Postal code citystreetNumber(required): Street numberstreetName(optional): Street namehouseNumber(required): House numberlat(optional): Latitude coordinatelon(optional): Longitude coordinateorderDate(optional): Order placement date (YYYY-MM-DD format)deliveryDate(required): Delivery date (YYYY-MM-DD format, today or future)totalVolume(required): Total volume in cubic meterstotalWeight(required): Total weight in kilogramsorderDimensions(optional): Package dimensions objectlot(optional): Lot/batch identifierbag(optional): Bag identifierboxes(optional): List of box identifiersaddressNotes(optional): Notes about the addressserviceType(optional):"delivery"or"collection"invoiceNumber(optional): Associated invoice number (set automatically in the invoice flow)itemsQuantity(optional): Total number of parcels sharing the same invoice (used for label printing, e.g. 1/3)
Dimensions
length(required): Length in meterswidth(required): Width in metersheight(required): Height in meters
Slot
slotFrom(optional): Start of delivery slot (HH:MM format)slotTo(optional): End of delivery slot (HH:MM format)
Payment
paymentBoolean(optional): Payment status (true if paid)value(optional): Payment amount in eurospaymentType(optional): Type of payment (e.g., "card")
InvoiceModel
invoiceNumber(required): Invoice identifierdeliveryDate(required): Delivery date in YYYY-MM-DD format (today or future)customerInfo(required): Recipient information shared by all parcelsaddress(required): Delivery address shared by all parcelsorders(required): List of parcels (at least 1, maximum 99)
InvoiceAddress
addressLine(optional): Full address linecountry(optional, default"Portugal"): Country namelocality(required): City/localitypostalCode(required): Postal codestreetNumber(optional): Street numberstreetName(optional): Street namehouseNumber(optional): House numberlat(optional): Latitude coordinatelon(optional): Longitude coordinateaddressNotes(optional): Notes about the address
InvoiceOrderItem
size(optional): Package size code (1–5)totalVolume(required): Volume in m³totalWeight(required): Weight in kgorderDimensions(optional): Physical dimensionslot(optional): Lot/batch identifierserviceType(optional):"delivery"or"collection"slot(optional): Delivery time slotpayment(optional): Payment detailsgenerateLabel(optional): Request PDF label generation (defaultfalse)
InvoiceAddressUpdate
invoiceNumber(required): Invoice numberaddressLine(optional): Full address linepostalCode(required): Postal codelatitude(optional): Latitude coordinatelongitude(optional): Longitude coordinateaddressNotes(optional): Notes about the addressgenerateLabel(optional): Request PDF label generation (defaultfalse)
CancelInvoiceRequest
invoiceNumber(required): Invoice number to cancel/uncancelcancel(required):trueto cancel,falseto reactivate
Development and Deployment
Local Development
# Install dependencies
poetry install
# Run the FastAPI application
uvicorn main:app --reload --host 0.0.0.0 --port 8080
Deployment
The API is automatically deployed using Google Cloud Build when changes are pushed to the main branch. The deployment process includes:
- Building the Docker image
- Pushing to Google Artifact Registry
- Deploying to Google Cloud Run
- Updating the API Gateway configuration
Configuration
The API uses the following environment variables:
PROJECT_ID: Google Cloud Project IDFIREBASE_API_KEY: Firebase API key for authenticationMONGODB_*: MongoDB connection parametersGOOGLE_MAPS_API_KEY: Google Maps API key for address validationBIGQUERY_*: BigQuery configuration for order storageOSRM_HOST: OSRM server URL for route calculationsBO_API_KEY: Backend API key for internal communicationsBOURL: Backend API URL