Introduction
The Qapla' v2 API provides an advanced platform for both reading and writing integration with proprietary e-commerce systems or those that do not have a specific plugin or connector available.
The architecture is based on a RESTful style that ensures intuitive resource management and compliance with international standards, simplifying integration and process automation.
- The API is structured according to REST principles (RESTful API).
- It supports GET, POST, PUT, DELETE, and PATCH requests, using the JSON format for both sending and receiving data.
- Responses include HTTP status codes to indicate the result of the request (HTTP Status Codes).
- Timestamps on parcels and orders resources are ISO 8601 and carry a
+00:00 suffix (YYYY-MM-DDTHH:MM:SS+00:00). Do not rely on that offset: it is appended without conversion, while the stored value is Europe/Rome local time — so the instant it denotes is off by the Rome offset. Treat these fields as local time, exactly like the tracking ones below. The one exception is orders ingested through the Qapla' import pipeline, which are genuine UTC; the response does not distinguish the two cases.
- Shipment tracking timestamps —
statusDate, statusUpdatedAt and history[].date on /v2/shipments — and the timestamps on sandbox resources are returned as YYYY-MM-DD HH:MM:SS without an offset and expressed in Europe/Rome local time, not UTC. The updatedAfter filter is interpreted in that same time zone.
- Date-only fields, such as
shipDate and orderDate, use YYYY-MM-DD.
⚠
The shipment tracking timestamps described above will move to UTC with an explicit offset
in a future version of the API. The change will be announced in advance.
Do not hard-code the Europe/Rome assumption in your integration: read the offset when one is present,
and treat a timestamp without an offset as local time.
API Key
To use the APIs, you must have a private API Key, which is assigned to the enabled channels.
You can find the API Key in the Control Panel under the "Settings" > "Channels" section.
The API Key must be kept confidential and secure.
Each channel has one or more private API Keys, which define the permissions and accessible endpoints.
Authentication
Authentication follows the Bearer Token Authentication flow: exchange your API Key for a JWT token, then include it in every request.
To obtain an access token, send a POST request to the authentication endpoint with your API Key:
POST https://api.qapla.it/v2/auth/token
The request must contain the following JSON in the body:
{"apiKey":"API_KEY"}
Access token cURL request:
curl -X POST https://api.qapla.it/v2/auth/token \
-H "Content-Type: application/json" \
-d '{"apiKey": "API_KEY"}'
Response Body 200
Description
| token (string) |
The JWT token to include as Bearer in the Authorization header of all subsequent requests. |
| scopes (array) |
List of permissions granted to the current API Key (e.g. parcels:create, sandbox:read). |
| token_type (string) |
Indicates the type of token (always Bearer). |
| expires_in (int) |
Token duration in seconds (86400 = 24 hours). |
| rate_limit (object) |
Token Bucket parameters configured for this API Key.
| refill_rate (int) |
Tokens added to the bucket per minute. |
| bucket_size (int) |
Maximum bucket capacity (maximum burst requests). |
|
| cache (bool) |
Indicates whether the response was served from cache (true) or freshly generated (false). |
Errors
| 400 |
Bad Request: the request body is missing or is not valid JSON. |
| 401 |
Unauthorized: the API Key is invalid or the channel is inactive. |
| 422 |
Unprocessable Content: the apiKey field is missing, empty or not a string. |
| 429 |
Too Many Requests: rate limit exceeded. |
Using the token
The token must be included in the
Authorization header of all requests, preceded by
Bearer:
curl -X GET https://api.qapla.it/v2/endpoint \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json"
Errors
All errors returned by the Qapla' API are represented using standard HTTP status codes.
Each code indicates the type of error encountered while processing the request, providing a clear and standard-compliant indication of any authentication, validation, or incorrect endpoint usage issues.
HTTP Status Codes
400 |
Bad Request: The request is invalid or required parameters are missing from the request body. |
401 |
Unauthorized: The API Key is invalid or does not have the necessary permissions to access the requested endpoint. |
403 |
Forbidden: Access denied. The API Key does not have the necessary permissions or the user is not authorized. |
404 |
Not Found: The specified endpoint does not exist or the requested resource was not found. |
405 |
Method Not Allowed: The HTTP method used (GET, POST, PUT, DELETE) is not supported for this endpoint. |
406 |
Not Acceptable: The server is unable to generate a response in the requested format or language. |
409 |
Conflict: The request cannot be completed due to a conflict with the current state of the resource. |
423 |
Locked: The requested resource is locked and cannot be modified or accessed. |
429 |
Too Many Requests: The maximum number of requests has been exceeded. Please wait before trying again. |
500 |
Internal Server Error: An internal server error occurred while processing the request. |
503 |
Service Unavailable: The service is currently unavailable. Please try again later. |
Body
JSON error body.
| status |
The type of error. |
| code |
The internal error code. |
| message |
The error description. |
Header
| X-Error-Message |
The descriptive error text. |
Usage Limits
The request management system uses a Token Bucket algorithm to limit the number of API calls within a specified time interval. The limit applies per channel and is shared by all the API Keys of that channel, with the following parameters:
| Bucket capacity |
300 |
Maximum number of requests absorbed in a burst, before throttling starts. |
| Tokens per minute |
150 |
The bucket refills at a rate of 150 tokens per minute. |
| Token cost |
1 |
Every request consumes one token, regardless of how many elements the body carries. |
Channels with high volumes can be granted a dedicated allowance above the standard one: contact Customer Support. The values assigned to your API Key are always readable in the rate_limit object returned by POST /auth/token.
HTTP Response Status Codes
If the usage limit is exceeded, the response will be:
429 Too Many Requests
The response carries the X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers. Retry honouring the Retry-After header, with exponential backoff.
Abuse
Repeated abuse of the API (10 or more 429 responses within 5 minutes) results in an automatic 1-hour suspension of the API Key (403 Forbidden). Permanent revocation is managed manually by the system administrator.
Postman Collection

A
Postman Collection is available.
Swagger UI

An interactive
Swagger UI is available to explore and test the API endpoints.
Authentication
The authentication service lets you obtain a JWT token from your API Key. The token is valid for 24 hours and must be included as Bearer in the Authorization header of every request.
POSTAuth / Token
Exchanges an API Key for a JWT token valid for 24 hours. The token can be cached and reused until expiry.
POSThttps://api.qapla.it/v2/auth/token
Body
*Required parameter
| apiKey*(string) |
The channel's private API Key. Available in the Control Panel under "Settings" > "Channels" > "Configure". |
This endpoint does not require authentication (no Authorization header).
Body 200
| token(string) |
The JWT token to include as Bearer in the Authorization: Bearer {token} header of every subsequent request. |
| scopes(array) |
List of permissions granted to the API Key. Each scope corresponds to a specific action on a resource.
parcels:create, parcels:read, parcels:update, parcels:delete,
sandbox:read, sandbox:write, orders:read, orders:write,
labels:read, labels:write, jobs:read, shipments:create, shipments:read
|
| token_type(string) |
Token type (always Bearer). |
| expires_in(int) |
Token duration in seconds. Fixed value: 86400 (24 hours). |
| rate_limit(object) |
Token Bucket parameters for this API Key.
| refill_rate(int) |
Tokens added to the bucket per minute. |
| bucket_size(int) |
Maximum bucket capacity. |
|
| cache(bool) |
true if the response was served from Redis cache (existing token), false if freshly generated. |
Response Headers
| X-Auth-Cache(string) |
HIT if the token was served from cache, MISS if freshly generated. |
Errors
| 400 |
Bad Request: the request body is missing or is not valid JSON. |
| 401 |
Unauthorized: the API Key is invalid or the channel is inactive. |
| 422 |
Unprocessable Content: the apiKey field is missing, empty or not a string. |
| 429 |
Too Many Requests: rate limit exceeded. |
Sandbox
The Sandbox APIs are test endpoints that allow you to verify your integration without side effects on real data. Each sandbox entity exposes all standard HTTP methods (CRUD) and includes values of every type (string, int, bool, float, datetime).
A Sandbox entity is uniquely identified by its numeric id.
Required scopes: sandbox:read for GET, sandbox:write for POST/PUT/PATCH/DELETE.
GETSandbox
Returns a paginated list of Sandbox entities. Supports temporal filters via query parameters.
GEThttps://api.qapla.it/v2/sandbox
Query Parameters
| page(int) |
Page number. Default: 1. |
| limit(int) |
Results per page. Default: 20. |
| updatedAfter(string) |
Filter entities updated after this date (ISO 8601 format, e.g. 2024-01-15T00:00:00+01:00). |
| updatedBefore(string) |
Filter entities updated before this date (ISO 8601 format). |
Header
| Authorization(string) |
Bearer ACCESS_TOKEN |
Body 200
| items(array) |
List of sandbox entities for the current page. |
| total(int) |
Total number of entities. |
| page(int) |
Current page. |
| limit(int) |
Items per page. |
| pages(int) |
Total number of pages. |
Errors
All errors returned by the Qapla' API are represented using
standard HTTP status codes.
GETSandbox / {id}
Retrieves data for a single Sandbox entity by its numeric identifier.
GEThttps://api.qapla.it/v2/sandbox/{id}
Parameters
| id(int) |
The numeric identifier of the Sandbox entity. |
Body 200
| id(int) |
Unique identifier of the entity. |
| stringValue(string) |
String value. |
| intValue(int) |
Integer value. |
| boolValue(bool) |
Boolean value. |
| floatValue(float) |
Decimal value. |
| dateTimeValue(string) |
Datetime value in ISO 8601 format. |
| createdAt(string) |
Creation date in ISO 8601 format. |
| updatedAt(string) |
Last update date in ISO 8601 format. |
Errors
| 400 |
Bad Request: id must be an integer greater than zero. |
| 404 |
Not Found: entity not found. |
POSTSandbox
Creates a new Sandbox entity. Returns the created entity with HTTP 201 and a
Location header pointing to the new resource.
POSThttps://api.qapla.it/v2/sandbox
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| stringValue*(string) |
String value. Minimum length: 3 characters. |
| intValue*(int) |
Integer value. |
| boolValue*(bool) |
Boolean value. |
| floatValue*(float) |
Decimal value. |
| dateTimeValue(string) |
Datetime value in Y-m-d H:i:s format (optional). |
Body 201
Header
| Location(string) |
URL of the created resource, e.g. /v2/sandbox/42. |
Errors
| 422 |
Unprocessable Entity: validation error on request fields. |
PUTSandbox / {id}
Fully replaces a Sandbox entity. All fields are required.
PUThttps://api.qapla.it/v2/sandbox/{id}
Parameters
| id(int) |
The numeric identifier of the entity to replace. |
Body
*Required parameter
| stringValue*(string) |
String value. Minimum length: 3 characters. |
| intValue*(int) |
Integer value. |
| boolValue*(bool) |
Boolean value. |
| floatValue*(float) |
Decimal value. |
| dateTimeValue(string) |
Datetime value in Y-m-d H:i:s format (optional). |
Body 200
Errors
| 404 |
Not Found: entity not found. |
| 422 |
Unprocessable Entity: validation error on request fields. |
PATCHSandbox / {id}
Partially updates a Sandbox entity. Only the fields included in the body are modified.
PATCHhttps://api.qapla.it/v2/sandbox/{id}
Parameters
| id(int) |
The numeric identifier of the entity to update. |
Body
All fields are optional. Only fields present in the body are updated.
| stringValue(string) |
String value. Minimum length: 3 characters. |
| intValue(int) |
Integer value. |
| boolValue(bool) |
Boolean value. |
| floatValue(float) |
Decimal value. |
| dateTimeValue(string) |
Datetime value in Y-m-d H:i:s format. |
Body 200
Errors
| 404 |
Not Found: entity not found. |
| 422 |
Unprocessable Entity: validation error on fields. |
DELETESandbox / {id}
Deletes a Sandbox entity by its id. Returns HTTP 204 with no body.
DELETEhttps://api.qapla.it/v2/sandbox/{id}
Parameters
| id(int) |
The numeric identifier of the entity to delete. |
Response
HTTP 204 No Content — no body in the response.
Errors
| 404 |
Not Found: entity not found. |
Shipments
The Shipments APIs cover the whole shipment lifecycle: synchronous bulk creation (up to 100 per request), asynchronous mass import (up to 5000, with a background job), paginated search with combinable filters, and full detail with tracking history and notifications. They also include stock release (svincolo giacenza), which asks the courier to act on a shipment held in depot: re-deliver it, re-deliver it to a new address, or return it to the sender.
A shipment is uniquely identified by its numeric id, returned at creation time, and always belongs to the authenticated channel.
Required scopes: shipments:read for search and detail, shipments:write for creation, import and stock release.
POSTCreate shipments
Creates up to
100 shipments in a single synchronous request. Each shipment is validated and created individually: the outcome is reported per item in the
items array of the response, in the same order as the request.
The response is 201 when every shipment was created, 207 Multi-Status when one or more shipments were rejected (partial or total failure: check items[].errors). Static payload violations (missing required fields, invalid formats) reject the whole request with 422 instead (RFC 7807 with violations).
For volumes above 100 shipments use the asynchronous import POST /shipments/import.
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: shipments:write. Shipments are created on the authenticated channel.
POSThttps://api.qapla.it/v2/shipments
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| shipments*(array) |
Shipments to create (minimum 1, maximum 100). Each shipment contains the following fields:
| trackingNumber*(string) |
Tracking number assigned by the courier (max 50 characters). |
| courier*(string) |
Courier of the shipment: Qapla' code (e.g. UPS), name, or channel-specific transcoding. Courier variants must be enabled for the channel, otherwise the item is rejected with COURIER_NOT_CONFIGURED. |
| shipDate*(string) |
Ship date, YYYY-MM-DD format. |
| orderReference(string) |
Merchant order reference. |
| orderDate(string) |
Order date, YYYY-MM-DD format. |
| platformOrderId(string) |
Order id on the source platform. |
| origin(string) |
Source platform of the order (e.g. magento, shopify, amazon). When provided it must exist in the platform registry, otherwise INVALID_ORIGIN. |
| language(string) |
Notification language (ISO 639-1, e.g. it, en). Default: it. Must be a supported language, otherwise INVALID_LANGUAGE. |
| tag(string) |
Free-text tag of the shipment. |
| note(string) |
Free-text note of the shipment. |
| isRealTrackingNumber(bool) |
false when the tracking number is a placeholder not yet assigned by the courier. Default: true. |
| isReturnable(bool) |
Whether the shipment can be returned. Default: true. |
| commercialContactEmail(string) |
Email of the commercial contact for this order. |
| consignee(object) |
Recipient of the shipment. Email and phone are only needed to enable transactional notifications: a shipment without them is still created.
| name(string) |
Full name. |
| street(string) |
Street address. |
| city(string) |
City. |
| postcode(string) |
ZIP / postal code. |
| state(string) |
State / province (e.g. MI). |
| country(string) |
Country (ISO 3166-1 alpha-2). Default: IT. |
| email(string) |
Recipient email (enables email notifications). |
| phone(string) |
Recipient phone (enables SMS notifications). |
|
| monetary(object) |
Monetary information of the shipment.
| totalValue(float) |
Total order value. |
| codAmount(float) |
Cash on delivery amount. A value greater than zero marks the shipment as COD. |
| shippingCost(float) |
Shipping cost paid by the customer. |
| currency(string) |
Currency (ISO 4217). Only EUR is currently supported. |
|
| planning(object) |
Delivery planning.
| deliveryDate(string) |
Expected delivery date (YYYY-MM-DD). |
| latestShipDate(string) |
Latest useful ship date (YYYY-MM-DD). |
| latestDeliveryDate(string) |
Latest useful delivery date (YYYY-MM-DD). |
|
| customAttributes(object) |
Merchant-defined custom attributes, searchable via GET /shipments.
| custom1(string) |
Custom field 1. |
| custom2(string) |
Custom field 2. |
| custom3(string) |
Custom field 3. |
|
| parcels(array) |
Parcels of the shipment (maximum 100). For each parcel: provide boxCode (dimensions come from the company box registry; weight is still required), or the full set weight + length + width + height. Otherwise the item is rejected with INVALID_BOX_CODE or MISSING_PARCEL_DIMENSIONS.
| id(string) |
Client-side parcel identifier, referenced by orderItems[].parcelId. |
| trackingNumber(string) |
Parcel-specific tracking number, when the courier assigns one per parcel. |
| weight*(float) |
Weight in kg. Always required. |
| length(float) |
Length in cm. Required when boxCode is not provided. |
| width(float) |
Width in cm. Required when boxCode is not provided. |
| height(float) |
Height in cm. Required when boxCode is not provided. |
| boxCode(string) |
Code of a box from the company box registry (provides the dimensions). |
| content(string) |
Free-text description of the parcel content. |
| originCountry(string) |
Origin country of the goods (ISO 3166-1 alpha-2). |
|
| orderItems(array) |
Order lines of the shipment (maximum 500).
| sku*(string) |
Product SKU. |
| name*(string) |
Product name. |
| quantity(int) |
Quantity. Default: 1. |
| price(float) |
Unit price. |
| total(float) |
Line total (price × quantity). |
| weight(float) |
Gross weight in kg. |
| netWeight(float) |
Net weight in kg. |
| unitOfMeasurement(string) |
Unit of measurement (e.g. pcs). |
| url(string) |
Product page URL. |
| imageUrl(string) |
Product image URL. |
| isReturnable(bool) |
Whether the item can be returned. Default: true. |
| customsCode(string) |
Customs (HS) code. |
| originCountry(string) |
Origin country of the item (ISO 3166-1 alpha-2). |
| parcelId(string) |
Id of the parcel containing the item (reference to parcels[].id). |
| transparencyCodes(array) |
Amazon Transparency codes (array of strings). |
| notes(string) |
Free-text notes of the line. |
| custom1…custom5(string) |
Line custom fields (custom1 to custom5). |
|
|
Body 201 — all shipments created
| summary(object) |
Batch summary.
| totalRequested(int) |
Shipments in the request. |
| totalSuccess(int) |
Shipments created. |
| totalFailed(int) |
Shipments rejected. |
|
| items(array) |
Per-item outcomes, in the same order as the request.
| status(string) |
Item outcome: success or error. |
| trackingNumber(string) |
Tracking number of the request item. |
| id(int) |
Id of the created shipment. null on error. |
| trackingUrl(string) |
Public tracking page URL of the created shipment. null on error. |
| errors(array) |
Item errors, present when status is error.
| code(string) |
Machine-readable error code (see table below). |
| message(string) |
Human-readable message. |
| field(string) |
Field the error refers to, when applicable. |
|
|
Body 207 — partial or total failure (Multi-Status)
Per-item error codes
| INVALID_COURIER |
The courier value does not match any active courier (neither as code, name nor channel transcoding). |
| COURIER_NOT_CONFIGURED |
The courier variant exists but is not enabled for the authenticated channel. |
| INVALID_LANGUAGE |
The language specified in language is not supported. |
| INVALID_ORIGIN |
The platform specified in origin does not exist in the platform registry. |
| DUPLICATE_SHIPMENT |
A shipment with the same channel + courier + trackingNumber triple already exists. Duplicates are detected within the same batch as well. |
| INVALID_BOX_CODE |
The specified boxCode does not exist in the company box registry (or the registry is empty). |
| MISSING_PARCEL_DIMENSIONS |
A parcel without boxCode is missing the full set weight + length + width + height. |
| INTERNAL_ERROR |
Unexpected internal error while creating the item. |
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: channel context missing from the token, or the token lacks the shipments:write scope. |
| 422 |
Unprocessable Entity: static payload violations (RFC 7807 with violations). The whole request is rejected, no shipment is created. |
| 429 |
Too Many Requests: rate limit exceeded. |
POSTImport shipments (asynchronous)
Imports up to
5000 shipments in a single asynchronous request. The request queues a background job and immediately replies
202 with the job coordinates; the per-shipment outcome is obtained by polling the job.
Each shipment has the same format as POST /shipments and is processed with the same business rules. Unlike the synchronous endpoint, static validation errors do not block the batch either: an invalid item fails alone with code VALIDATION_ERROR.
The import is safe to retry: if the job is re-executed after an interruption, items already inserted are reported as DUPLICATE_SHIPMENT without double insertions.
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: shipments:write. Shipments are created on the authenticated channel.
POSThttps://api.qapla.it/v2/shipments/import
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| shipments*(array) |
Shipments to import (minimum 1, maximum 5000). Each shipment has the same format documented in POST /shipments. |
| webhookUrl(string) |
URL notified when the import completes (optional). The notification is best-effort: always use job polling as the source of truth. |
Body 202 — job accepted
| jobId(string) |
Identifier of the asynchronous job. |
| status(string) |
Initial job status: processing. |
| statusUrl(string) |
Relative URL to check the job status (/jobs/{jobId}). |
| totalShipments(int) |
Number of shipments queued. |
Job polling
Poll GET /v2/jobs/{jobId} to follow the progress (statuses: pending, processing, completed, failed; required scope: jobs:read). Once the job is finished, the result field contains the summary, the successes in compact form and the errors in detailed form:
| result.summary(object) |
Batch summary: totalRequested, totalSuccess, totalFailed. |
| result.successes(array) |
Created shipments, compact form: index (position in the request array), id, trackingNumber, trackingUrl (public tracking page URL). |
| result.errors(array) |
Rejected shipments, detailed form: index, trackingNumber and the errors[] array with code, message, field. The codes are the same as POST /shipments, plus VALIDATION_ERROR for statically invalid items. |
The failed status is reserved for the case where every shipment failed (or an infrastructure error); a partial failure leaves the job completed with the errors in result.errors.
Webhook
If you provided webhookUrl, Qapla' sends a best-effort POST at the end of the job with body {"jobId": "...", "status": "completed|failed", "result": {...}}, where result has the same structure shown above.
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: channel context missing from the token, or the token lacks the shipments:write scope. |
| 422 |
Unprocessable Entity: malformed body, empty shipments array or more than 5000 items, invalid webhookUrl (RFC 7807 with violations). |
| 429 |
Too Many Requests: rate limit exceeded. |
GETSearch shipments
Returns the paginated list of shipments of the authenticated channel. All filters are optional and combine with
AND semantics; without filters the endpoint is a plain paginated listing of the channel.
Polling tip
To synchronize tracking updates use the updatedAfter filter: it returns only shipments whose status changed after that moment, avoiding repeated per-shipment requests.
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: shipments:read.
GEThttps://api.qapla.it/v2/shipments?updatedAfter={DATETIME}&status={STATUS}&page={PAGE}
Query Parameters
| trackingNumber(string) |
Tracking number, exact match. |
| orderReference(string) |
Order reference, exact match. |
| custom1(string) |
Custom attribute 1, exact match. |
| custom2(string) |
Custom attribute 2, exact match. |
| custom3(string) |
Custom attribute 3, exact match. |
| shipDateFrom(string) |
Ship date from, inclusive (YYYY-MM-DD). |
| shipDateTo(string) |
Ship date to, inclusive (YYYY-MM-DD). |
| status(string) |
Comma-separated list of tracking status values (e.g. 3,4,99). See the status legend below. |
| updatedAfter(string) |
Only shipments whose tracking status changed at or after this moment (YYYY-MM-DD HH:MM:SS). Shipments never updated are excluded. Recommended for polling updates. |
| page(int) |
Page number. Default: 1. |
| limit(int) |
Results per page. Default: 20, maximum: 100. |
| sortBy(string) |
Sort order: id_desc (default), id_asc, shipDate_desc, shipDate_asc. |
Tracking statuses
| 0 |
WAITING_TO_COMPUTE — Waiting to be processed. |
| 1 |
PENDING — Waiting for the first tracking event. |
| 2 |
INFO_RECEIVED — The courier received the shipment data. |
| 3 |
IN_TRANSIT — In transit. |
| 4 |
OUT_FOR_DELIVERY — Out for delivery. |
| 5 |
FAILED_ATTEMPT — Failed delivery attempt. |
| 6 |
EXCEPTION — Exception (e.g. held in depot). |
| 8 |
DELAY — Delayed. |
| 10 |
PICKUP_POINT — Delivered to the pickup point. |
| 20 |
DEPARTED — Departed. |
| 50 |
PROCESSING — Being processed by the courier. |
| 95 |
RETURNED — Returned to sender. |
| 99 |
DELIVERED — Delivered. |
Body 200
| items(array) |
Shipments of the current page (summary projection; for parcels, order lines, history and notifications use GET /shipments/{id}).
| id(int) |
Shipment id. |
| trackingNumber(string) |
Courier tracking number. |
| trackingUrl(string) |
Public tracking page URL. null when the tracking token is not available. |
| courier(string) |
Canonical courier code. |
| courierName(string) |
Canonical courier name. |
| status(int) |
Tracking status (see the legend in the REQUEST tab). |
| statusDescription(string) |
Status description, localized in the shipment language. |
| statusDetail(int) |
Status detail id (0 = none). |
| statusDetailDescription(string) |
Status detail description, localized. |
| statusDate(string) |
Date of the last tracking event as reported by the courier. |
| statusUpdatedAt(string) |
When the tracking status last changed on Qapla'. This is the field the updatedAfter filter acts on. |
| statusPlace(string) |
Place of the last tracking event. |
| shipDate(string) |
Ship date (YYYY-MM-DD). |
| orderReference(string) |
Merchant order reference. |
| platformOrderId(string) |
Order id on the source platform. |
| orderDate(string) |
Order date (YYYY-MM-DD). |
| tag(string) |
Free-text tag of the shipment. |
| note(string) |
Free-text note of the shipment. |
| origin(string) |
Source platform of the order. |
| isReturn(bool) |
Whether this shipment is a return. |
| consignee(object) |
Recipient: name, street, city, postcode, state, country, email, phone. |
| monetary(object) |
Monetary information: totalValue, codAmount, shippingCost, currency. |
| customAttributes(object) |
Merchant-defined custom attributes: custom1, custom2, custom3. |
|
| total(int) |
Total number of shipments matching the filters. |
| page(int) |
Current page. |
| limit(int) |
Shipments per page. |
| pages(int) |
Total number of pages. |
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: channel context missing from the token, or the token lacks the shipments:read scope. |
| 422 |
Unprocessable Entity: invalid query parameters (e.g. unknown status values, malformed updatedAfter, limit > 100). |
| 429 |
Too Many Requests: rate limit exceeded. |
GETShipment details
Returns the full detail of a shipment: all the summary fields of
GET /shipments plus delivery planning, parcels, order lines, tracking history and sent notifications.
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: shipments:read. The shipment must belong to the authenticated channel: a shipment of another channel returns 404, indistinguishable from a non-existing one.
GEThttps://api.qapla.it/v2/shipments/{id}
Path
| id*(int) |
Numeric id of the shipment (returned at creation time or by GET /shipments). |
Body 200
The summary fields (id, trackingNumber, trackingUrl, courier, courierName, status, statusDescription, statusDetail, statusDetailDescription, statusDate, statusUpdatedAt, statusPlace, shipDate, orderReference, platformOrderId, orderDate, tag, note, origin, isReturn, consignee, monetary, customAttributes) are documented in GET /shipments. In addition, the detail includes:
| planning(object) |
Delivery planning: deliveryDate, latestShipDate, latestDeliveryDate. |
| parcels(array) |
Parcels of the shipment, as recorded at creation time.
| id(string) |
Client-side parcel identifier. |
| trackingNumber(string) |
Parcel-specific tracking number. |
| weight(float) |
Weight in kg. |
| length(float) |
Length in cm. |
| width(float) |
Width in cm. |
| height(float) |
Height in cm. |
| boxCode(string) |
Box registry code used at creation. |
| content(string) |
Parcel content description. |
| originCountry(string) |
Origin country of the goods (ISO 3166-1 alpha-2). |
|
| orderItems(array) |
Order lines of the shipment: sku, name, quantity, price, total, weight, netWeight, unitOfMeasurement, url, imageUrl, isReturnable, customsCode, originCountry, parcelId, notes, custom1…custom5. |
| history(array) |
Tracking history, most recent first.
| date(string) |
Event date (YYYY-MM-DD HH:MM:SS). |
| courierStatus(string) |
Raw status as reported by the courier. |
| place(string) |
Event place. |
| status(string) |
Mapped Qapla' status description. |
| statusCode(string) |
Mapped Qapla' status code (e.g. IN_TRANSIT, DELIVERED). |
| statusDetail(string) |
Status detail description, when present. |
|
| notifications(array) |
Notifications sent for this shipment.
| type(string) |
Notification type: email, sms or webhook. |
| result(string) |
Outcome: OK or KO. |
| date(string) |
Sent at (YYYY-MM-DD HH:MM:SS). |
| recipient(string) |
Recipient (email address, phone number or URL). |
| shipmentStatus(string) |
Shipment status at notification time. |
| error(string) |
Error detail, when the outcome is KO. |
|
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: channel context missing from the token, or the token lacks the shipments:read scope. |
| 404 |
Not Found: the shipment does not exist, or does not belong to the authenticated channel. |
| 429 |
Too Many Requests: rate limit exceeded. |
POSTRequest a stock release
Asks the courier to act on a shipment currently held in depot (
giacenza): re-deliver it, re-deliver it to a new address, or return it to the sender.
The response is always accepted synchronously (status: "sent"); the real outcome is carried by courierOutcome. GLS and TNT reply synchronously (ok/error); BRT is deferred — the request is transmitted asynchronously and its outcome (pending) becomes visible later through the shipment's tracking events.
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: shipments:write. The shipment must belong to the authenticated channel and be currently held in depot.
POSThttps://api.qapla.it/v2/shipments/{id}/stock-release
Path
| id*(int) |
Numeric id of the shipment held in depot. |
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| action*(string) |
Canonical action: redeliver, redeliver_new_address or return_to_sender. |
| notes(string) |
Free-text note for the courier (optional). |
| redeliveryDate(string) |
Requested redelivery date, ISO format (YYYY-MM-DD). Only allowed for redeliver and redeliver_new_address (a 422 is returned with return_to_sender). GLS requires a redelivery date: when omitted it defaults to the next Italian working day. Ignored by couriers that do not support it. |
| address(object) |
New delivery address. Required if and only if action is redeliver_new_address (a 422 is returned otherwise, either missing when required or present when not allowed).
| name*(string) |
Recipient name. |
| street*(string) |
Street address. |
| city*(string) |
City. |
| zip*(string) |
ZIP / postal code. |
| province*(string) |
Province code (e.g. MI). |
| phone(string) |
Contact phone (optional). |
|
Body 200
| status(string) |
Always sent — the request was accepted and transmitted to the courier. |
| courierOutcome(string) |
Real courier outcome: ok or error for synchronous couriers (GLS, TNT), pending for deferred couriers (BRT). |
| message(string) |
Courier outcome message, when available. null otherwise. |
| releaseId(int) |
Internal id of the stored release request. |
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: channel context missing from the token, or the token lacks the shipments:write scope. |
| 404 |
Not Found: the shipment does not exist, or does not belong to the authenticated channel. |
| 409 |
Conflict: the shipment is not currently held in depot (no giacenza to release). |
| 422 |
Unprocessable Entity: validation error (invalid action, missing/unexpected address, invalid or not allowed redeliveryDate), or the carrier rejected the request. |
| 429 |
Too Many Requests: rate limit exceeded. |
Couriers
The Couriers APIs provide network-wide delivery benchmarks. Given a destination and a list of couriers, you can compare their delivery times and pick the fastest carrier for a specific lane, or score their overall efficiency on that lane.
The benchmark is anonymous and aggregated across all merchants (no PII); the origin macro-area is deduced server-side from the authenticated company.
Required scopes: delivery-times:read for the delivery-time comparison, efficiency-index:read for the efficiency index.
POSTCompare courier delivery times
Given a destination Italian postal code and a list of couriers, returns the couriers ranked
fastest-first by average delivery time (lead time), so you can choose the fastest carrier for that lane.
The origin is resolved down to the company seat postal code (CAP), deduced server-side from the authenticated company, and can be overridden via the originCap parameter. The data is an anonymous cross-merchant network benchmark (no PII). Metrics are expressed in calendar days: lead = shipped→delivered (primary metric, used for ranking), transit = departed→delivered (carrier-only, history starting ~2026).
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: delivery-times:read.
POSThttps://api.qapla.it/v2/couriers/delivery-times
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| destCap*(string) |
5-digit destination Italian postal code (e.g. 20100). |
| couriers(array) |
List of courier codes to compare (max 50). Optional: if omitted, the shipping-enabled couriers of the authenticated channel are used. |
| weightKg(float) |
Parcel weight in kg (must be > 0). When provided, selects the matching weight band for a weight-specific estimate. If omitted, a weight-agnostic estimate is returned. |
| originCap(string) |
Optional origin postal code (5 digits). Overrides the authenticated company seat CAP used for the finest origin-CAP grains. If omitted, the company seat CAP is used. |
| detail(string) |
Response verbosity: summary (default) returns the best courier plus a slim ranking; full returns the complete ranking with all percentiles, grain, weightBand and the couriers with insufficient data. |
Body 200
| destCap(string) |
The destination postal code that was requested. |
| originArea(string) |
Origin macro-area deduced from the authenticated company: NORD, CENTRO or SUD. null if not resolvable. |
| originCap(string) |
Origin postal code used for the finest origin_cap_dest* grains (the request originCap, otherwise the company seat CAP). null when the seat CAP is not a valid Italian CAP. |
| requestedWeightBand(string) |
The weight band that weightKg maps to (e.g. 2-5). null if weightKg was omitted. |
| best(object) |
The fastest courier. null when no courier has sufficient data.
| courierCode(string) |
The courier code, as supplied in the request. |
| leadMedian(int) |
Median lead time shipped→delivered, calendar days. |
| leadMean(float) |
Mean lead time shipped→delivered, calendar days, rounded to 1 decimal. |
| transitMedian(int) |
Median transit time departed→delivered, carrier-only, calendar days. |
| transitMean(float) |
Mean transit time departed→delivered, carrier-only, calendar days, rounded to 1 decimal. |
| sampleSize(int) |
Number of deliveries in the benchmark cell (last 12 months). |
|
| ranking(array) |
Couriers with data, ordered fastest-first; insufficient-data couriers are omitted (request detail: "full" to see them).
| position(int) |
1-based ranking position (fastest = 1). |
| courierCode(string) |
The courier code, as supplied in the request. |
| leadMedian(int) |
Median lead time (shipped→delivered) in calendar days. Primary ranking metric. |
| transitMedian(int) |
Median transit time (departed→delivered, carrier-only) in calendar days. |
| sampleSize(int) |
Number of deliveries in the benchmark cell (last 12 months). |
|
Full detail (detail: "full")
When the request sets detail: "full", the response returns the complete ranking. Each row adds status (ok | insufficient_data), level (the benchmark grain, from finest to coarsest: origin_cap_dest_weight | origin_cap_dest | area_cap_weight | cap_weight | area_cap | cap), weightBand, leadMean, transitMean (means in calendar days, float rounded to 1 decimal), leadP90, transitP90 and transitSampleSize, and the couriers with no data are included at the end with status: insufficient_data and null metrics. The ranking is ordered by lead time: median, then mean, then p90. There is no best field in the full form.
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: the token lacks the delivery-times:read scope. |
| 422 |
Unprocessable Entity: validation error (invalid destCap/originCap), or no couriers to compare (none provided and the channel has no shipping-enabled couriers). |
| 429 |
Too Many Requests: rate limit exceeded. |
POSTScore courier efficiency
Given a destination Italian postal code and a list of couriers, returns for each courier a
0–100 efficiency index on that lane, with a rank (best-first) and three sub-scores, so you can pick the best-performing carrier — not just the fastest.
The efficiency index blends three sub-scores with the fixed network weights 40/20/40: scoreSpeed (from the speed median), scoreConsistency (from the gap between p90 and median) and scoreReliability (from the failed/stock/exception rates of the lane). The origin is resolved down to the company seat postal code (CAP), deduced server-side from the authenticated company, and can be overridden via the originCap parameter. The data is an anonymous cross-merchant network benchmark (no PII). Speed metrics are expressed in calendar days (transit when available, otherwise lead).
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: efficiency-index:read.
POSThttps://api.qapla.it/v2/couriers/efficiency-index
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| destCap*(string) |
5-digit destination Italian postal code (e.g. 20100). |
| couriers(array) |
List of courier codes to score (max 50). Optional: if omitted, the shipping-enabled couriers of the authenticated channel are used. |
| weightKg(float) |
Parcel weight in kg (must be > 0). When provided, selects the matching weight band for a weight-specific score. If omitted, a weight-agnostic score is returned. |
| originCap(string) |
Optional origin postal code (5 digits). Overrides the authenticated company seat CAP used for the finest origin-CAP grains. If omitted, the company seat CAP is used. |
Body 200
| destCap(string) |
The destination postal code that was requested. |
| originArea(string) |
Origin macro-area deduced from the authenticated company: NORD, CENTRO or SUD. null if not resolvable. |
| originCap(string) |
Origin postal code used for the finest origin_cap_dest* grains (the request originCap, otherwise the company seat CAP). null when the seat CAP is not a valid Italian CAP. |
| requestedWeightBand(string) |
The weight band that weightKg maps to (e.g. 2-5). null if weightKg was omitted. |
| ranking(array) |
Couriers ordered best-first by efficiencyIndex. Couriers whose lane cell is suppressed (fewer than 20 deliveries) or has no usable speed are appended at the end with status: "insufficient_data", a null rank and null metrics.
| rank(int) |
1-based rank by efficiency index (best = 1); ties share a rank. null for insufficient-data couriers. |
| courierCode(string) |
The courier code, as supplied in the request. |
| status(string) |
ok when the lane has a usable benchmark, insufficient_data otherwise. |
| efficiencyIndex(float) |
Overall efficiency index 0–100 (higher is better), rounded to 1 decimal. 0.40·scoreSpeed + 0.20·scoreConsistency + 0.40·scoreReliability. |
| scoreSpeed(float) |
Speed sub-score 0–100, from the speed median, rounded to 1 decimal. |
| scoreConsistency(float) |
Consistency sub-score 0–100, from the gap between the p90 and the median, rounded to 1 decimal. |
| scoreReliability(float) |
Reliability sub-score 0–100, from the failed/stock/exception rates of the lane, rounded to 1 decimal. |
| level(string) |
Benchmark grain used (most specific available): origin_cap_dest_weight | origin_cap_dest | area_cap_weight | cap_weight | area_cap | cap. |
| sampleSize(int) |
Number of deliveries in the benchmark cell. |
| speedMedian(int) |
Speed median in calendar days (transit median if available, otherwise lead median); the basis of scoreSpeed. |
| speedP90(int) |
Speed p90 in calendar days (transit p90 if available, otherwise lead p90); the basis of scoreConsistency. |
| failedRate(float) |
Failed-delivery rate of the lane cell (fraction 0–1). |
| stockRate(float) |
Stock/storage rate of the lane cell (fraction 0–1). |
| exceptionRate(float) |
Exception rate of the lane cell (fraction 0–1). |
|
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: the token lacks the efficiency-index:read scope. |
| 422 |
Unprocessable Entity: validation error (invalid destCap/originCap), or no couriers to score (none provided and the channel has no shipping-enabled couriers). |
| 429 |
Too Many Requests: rate limit exceeded. |
Addresses
The Addresses APIs check that a postal address exists and can be printed on a label, returning it normalised with a confidence score. They are meant to catch bad addresses before the shipment is created, while fixing them is still cheap.
Two providers sit behind the same contract, selected with the provider parameter: geocode (the default) covers the whole world and is the only one returning coordinates; gls queries the GLS Italia street registry, covers Italian addresses only and requires GLS to be configured on the channel, but reports ZTL, difficult areas, serving branch and zone, and proposes alternative addresses when the submitted one is not conformant.
Every accepted request is metered, whatever the provider and whatever the outcome: an address with no match is not an error, it is a 200 with match.status set to NONE.
Required scope: addresses:check. The feature must also be active on the contract and enabled on the channel.
POSTVerify an address
Check that a postal address exists and can be printed on a label, returning it normalised with a confidence score. Use it
before creating the shipment, to catch bad addresses while fixing them is still cheap.
Two providers sit behind the same contract, selected with the provider parameter. geocode (the default) queries the geocoding service: it covers the whole world and is the only one returning coordinates. gls queries the GLS Italia street registry: Italian addresses only, and only for channels with GLS configured, but in exchange it reports ZTL (restricted traffic zone), difficult area, serving branch and zone, and when the address is not conformant it proposes the addresses it would accept.
An address with no match is not an error: the response is 200 with match.status set to NONE. The check ran, and the answer is that the address does not exist.
NB
Authentication uses the Bearer Token obtained from the authentication service. Required scope: addresses:check.
Every accepted request is metered, whatever the provider and whatever the outcome — including when the address is not found. Requests rejected before the check (403 and 422) are not metered.
POSThttps://api.qapla.it/v2/addresses/check
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| address*(object) |
The address to verify.
| street*(string) |
Street address, house number included (e.g. Via Roma 1). Max 255 characters. |
| city*(string) |
City. Max 255 characters. |
| postcode(string) |
Postal code. Max 20 characters. |
| state(string) |
State / province code (e.g. MI). Max 50 characters. |
| country(string) |
Country, ISO 3166-1 alpha-2 (2 characters). Defaults to IT when omitted. |
|
| provider(string) |
Backend to query: geocode (default) or gls. gls only accepts addresses with country set to IT and requires GLS to be configured on the channel. |
Body 200 — geocode provider
| provider(string) |
The provider that answered: geocode or gls. |
| match(object) |
How closely the returned address matches the submitted one.
| status(string) |
FULL when confidence is 90 or above, WARNING from 80 up, NONE below 80 or when nothing matched. |
| confidence(float) |
Score 0–100, comparable across both providers: it is 100 when the provider itself reports an exact hit, otherwise it measures how far the returned address is from the submitted one. null when nothing matched. |
| partial(bool) |
true when the provider matched only part of the address. |
|
| formatted(string) |
The normalised address on a single line. null when nothing matched. |
| components(object) |
The normalised address, part by part: street, city, postcode, state, region, country. null when nothing matched. region is only filled by providers that know about administrative regions.
|
| coordinates(object) |
Geographic coordinates (latitude, longitude) of the matched address. Filled only by the geocode provider: the GLS street registry does not geocode. |
| candidates(array) |
Alternative addresses proposed by the provider, with the same fields as components. Filled only by the gls provider, when the submitted address is not in the street registry. Empty array otherwise. |
| delivery(object) |
Delivery constraints the courier knows about the address. Filled only by the gls provider, null otherwise.
| restrictedTrafficZone(bool) |
The address is inside a restricted traffic zone (ZTL). |
| difficultArea(bool) |
The address is a difficult location: a surcharge usually applies. A ZTL always counts as a difficult area too. |
| branch(string) |
Courier branch serving the address. |
| zone(string) |
Courier delivery zone. |
|
Body 200 — gls provider, conformant address
No coordinates, but the delivery block is filled: here the address is inside a ZTL, so difficultArea is true as well.
Body 200 — gls provider, non-conformant address
The address is not in the GLS street registry: components is null and candidates lists the addresses GLS would accept.
Errors
| 401 |
Unauthorized: missing or invalid token. |
| 403 |
Forbidden: the token does not carry the addresses:check scope, address check is not active on your contract, or it is not enabled on the channel. |
| 422 |
Unprocessable Entity: validation error, or the requested provider cannot serve the request (gls with a non-Italian address, or on a channel without GLS configured). |
| 429 |
Too Many Requests: rate limit exceeded. |
| 502 |
Bad Gateway: the address check provider is unreachable or answered unreadably. |
Parcels
The Parcels APIs allow you to pre-load the packages of an order before the shipment (label) is created. The uploaded packages are then automatically inherited by the order or shipment.
A parcel is uniquely identified by a hash and belongs to an order via the orderReference + orderOrigin pair.
Required scopes: parcels:create, parcels:read, parcels:update, parcels:delete.
POSTParcels
Creates one or more parcels for an order. The response is
synchronous (≤10 parcels, HTTP 201) or
asynchronous (>10 parcels, HTTP 202 with
jobId).
Note
Authentication requires the Bearer Token obtained from the authentication service. Required scope: parcels:create.
POSThttps://api.qapla.it/v2/parcels
Body
The request body must be a JSON containing the following parameters:
*Required parameter
| order*(object) |
The order the parcels belong to.
| reference*(string) |
The unique order reference. |
| origin*(string) |
The order origin (e.g. shopify, amazon, woocommerce). |
|
| parcels*(array) |
List of parcels (minimum 1, maximum 100).
| originCountryIso*(string) |
ISO 3166-1 alpha-2 country code of origin (e.g. IT, ES). |
| weightKg*(float) |
Weight in kg, max 2 decimal places. Maximum 99 kg. |
| lengthCm(float) |
Length in cm, max 2 decimal places. |
| widthCm(float) |
Width in cm, max 2 decimal places. |
| heightCm(float) |
Height in cm, max 2 decimal places. |
| contentsDescription(string) |
Description of parcel contents. |
| clientInternalCode(string) |
Client's internal code. |
| shippingNotes(string) |
Notes to be printed on the label. |
|
| webhookUrl(string) |
Callback URL for async notifications (optional). |
Header
| x-label-format(string) |
PDF (default) or ZPL to get the label in the desired format. |
Body 201 — Synchronous response (≤10 parcels)
| parcelHash(string) |
Unique hash of the created parcel. Used to identify the parcel in GET, PATCH and DELETE calls. |
| parcelNumber(int) |
Progressive number of the parcel. |
| label |
The label in the requested format.
| format(string) |
Label format (PDF or ZPL). |
| label(string) |
Label content in Base64 (PDF) or ZPL text. |
|
| totalParcelCount(int) |
Total number of parcels for the order. |
Body 202 — Asynchronous response (>10 parcels)
| jobId(string) |
Async job identifier. Use GET /v2/jobs/{jobId} to monitor status. |
| status(string) |
Job status: pending, processing, completed, failed. |
| statusUrl(string) |
URL to check job status. |
| hashes(array) |
Pre-assigned hashes for the parcels. |
| totalParcels(int) |
Total number of parcels to process. |
Errors
| 422 |
Unprocessable Entity: validation error (e.g. empty parcels array or more than 100 parcels). |
| 429 |
Too Many Requests: rate limit exceeded. |
GETParcels
Returns a paginated list of parcels for an order, identified by the
orderReference +
orderOrigin pair passed as query parameters. Required scope:
parcels:read.
GEThttps://api.qapla.it/v2/parcels?orderReference={REFERENCE}&orderOrigin={ORIGIN}
Query Parameters
| orderReference*(string) |
The order reference. |
| orderOrigin*(string) |
The order origin (e.g. shopify, amazon). |
| page(int) |
Page number. Default: 1. |
| limit(int) |
Results per page. Default: 20. |
*Required parameter
Body 200
| items(array) |
List of parcels for the order. |
| total(int) |
Total number of parcels. |
| page(int) |
Current page. |
| limit(int) |
Parcels per page. |
| pages(int) |
Total number of pages. |
Errors
All errors returned by the Qapla' API are represented using
standard HTTP status codes.
GETParcels / {hash}
Retrieves data for a single parcel by its identifying hash. Required scope:
parcels:read.
GEThttps://api.qapla.it/v2/parcels/{PARCEL-HASH}
Parameters
| hash(string) |
The identifying hash of the parcel, obtained at creation time. |
Body 200
| parcelHash(string) |
Unique hash of the parcel. |
| parcelNumber(int) |
Progressive number of the parcel in the order. |
| label |
The label associated with the parcel (format + Base64 or ZPL content). |
| originCountryIso(string) |
ISO country code of origin. |
| clientInternalCode(string) |
Client's internal code. |
| weightKg(float) |
Weight in kg. |
| lengthCm(float) |
Length in cm. |
| widthCm(float) |
Width in cm. |
| heightCm(float) |
Height in cm. |
| contentsDescription(string) |
Contents description. |
| shippingNotes(string) |
Label notes. |
| createdAt(string) |
Creation date in ISO 8601 format. |
| updatedAt(string) |
Last update date in ISO 8601 format. |
Errors
| 404 |
Not Found: parcel not found. |
PATCHParcels / {hash}
Partially updates a parcel. Only the fields included in the body are modified. Required scope:
parcels:update.
PATCHhttps://api.qapla.it/v2/parcels/{PARCEL-HASH}
Parameters
| hash(string) |
The identifying hash of the parcel to update. |
Body
All fields are optional. Only fields present in the body are updated.
| weightKg(float) |
Weight in kg, max 2 decimal places. |
| lengthCm(float) |
Length in cm. |
| widthCm(float) |
Width in cm. |
| heightCm(float) |
Height in cm. |
| originCountryIso(string) |
ISO country code of origin. |
| contentsDescription(string) |
Contents description. |
| clientInternalCode(string) |
Client's internal code. |
| shippingNotes(string) |
Label notes. |
Body 200
Errors
| 404 |
Not Found: parcel not found. |
| 422 |
Unprocessable Entity: validation error on fields. |
DELETEParcels / {hash}
Deletes a single parcel identified by its hash. Returns HTTP 204 with no body. Required scope:
parcels:delete.
DELETEhttps://api.qapla.it/v2/parcels/{PARCEL-HASH}
Parameters
| hash(string) |
The identifying hash of the parcel to delete. |
Response
HTTP 204 No Content — no body in the response.
Errors
| 404 |
Not Found: parcel not found. |
DELETEParcels (bulk)
Deletes all parcels of an order, identified by the
orderReference +
orderOrigin pair passed as query parameters. Returns HTTP 204 with no body. Required scope:
parcels:delete.
DELETEhttps://api.qapla.it/v2/parcels?orderReference={REFERENCE}&orderOrigin={ORIGIN}
Query Parameters
| orderReference*(string) |
The order reference. |
| orderOrigin*(string) |
The order origin. |
*Required parameter
Response
HTTP 204 No Content — no body in the response.
Errors
| 404 |
Not Found: no parcels found for the specified order. |