openapi: 3.0.3
info:
title: parcelLab API
description: |
parcelLab API v4 Enhanced — the REST API for the parcelLab post-purchase
experience platform. Send orders and trackings, retrieve order status,
look up pickup/drop-off locations, predict delivery dates, manage return
registrations and configurations, evaluate marketing campaigns, and
publish surveys to your customers.
Regional base URLs are available for EU and US workloads in addition to
the global endpoint.
version: '4'
contact:
name: parcelLab Developer Support
url: https://docs.parcellab.com/docs/developers/readme
license:
name: Proprietary
url: https://parcellab.com/legal/terms-of-service/
servers:
- url: https://api.parcellab.com
description: Global production endpoint
- url: https://api.eu.parcellab.com
description: EU regional endpoint
- url: https://api.us.parcellab.com
description: US regional endpoint
tags:
- name: Orders
description: Create, update, and inspect orders and their trackings.
- name: Events
description: Send custom shop or warehouse events into the tracking timeline.
- name: Place Info
description: Look up nearby pickup and drop-off (PUDO) locations.
- name: Promise
description: Pre-checkout delivery date predictions.
- name: Returns
description: Return registrations, configurations, and document templates.
- name: Campaigns
description: Evaluate campaign targeting and redirect analytics events.
- name: Surveys
description: Retrieve survey definitions and submit responses.
security:
- parcellabApiToken: []
paths:
/v4/track/orders/:
put:
tags: [Orders]
summary: Create or Update Order
operationId: upsertOrder
description: >-
Idempotent endpoint that creates a new order or applies mutations to
an existing one (add or cancel trackings, change line item quantity,
add or replace line items, cancel order).
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderUpsertRequest'
responses:
'200':
description: Order updated.
content:
application/json:
schema:
$ref: '#/components/schemas/OrderUpsertResponse'
'201':
description: New order created.
content:
application/json:
schema:
$ref: '#/components/schemas/OrderUpsertResponse'
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
/v4/track/orders/info/:
get:
tags: [Orders]
summary: Get Order Status
operationId: getOrderInfo
description: >-
Retrieve the latest order, tracking, and checkpoint information for
an order identified by order_number, tracking_number,
external_order_id, or recipient identifiers.
parameters:
- { in: query, name: account, schema: { type: integer } }
- { in: query, name: order_number, schema: { type: string } }
- { in: query, name: tracking_number, schema: { type: string } }
- { in: query, name: courier, schema: { type: string } }
- { in: query, name: external_order_id, schema: { type: string, format: uuid } }
- { in: query, name: external_reference, schema: { type: string } }
- { in: query, name: customer_number, schema: { type: string } }
- { in: query, name: recipient_email, schema: { type: string, format: email } }
- { in: query, name: recipient_postal_code, schema: { type: string } }
- { in: query, name: client_key, schema: { type: string } }
- { in: query, name: lang, schema: { type: string, default: en } }
- { in: query, name: s, schema: { type: string }, description: HMAC security signature. }
- { in: query, name: live_refresh, schema: { type: boolean } }
- { in: query, name: show_returns, schema: { type: boolean } }
- { in: query, name: tracking_id, schema: { type: string } }
- { in: query, name: single_tracking, schema: { type: boolean } }
responses:
'200':
description: Order info.
content:
application/json:
schema:
$ref: '#/components/schemas/OrderInfo'
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v4/track/events/:
post:
tags: [Events]
summary: Send Shop or Warehouse Event
operationId: sendShopEvent
description: >-
Push a custom event/checkpoint (e.g., warehouse pick, pack, dispatch)
into the order timeline. Identifies the order by courier+tracking,
account+reference, or account+order_number.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ShopEvent'
responses:
'204': { description: Event accepted. }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v4/track/place-info/lookup/:
post:
tags: [Place Info]
summary: Look Up Pickup/Drop-Off Locations
operationId: lookupPlaceInfo
description: >-
Find nearby PUDO points for one or more couriers, ranked by distance
from a geo-coordinate or address.
parameters:
- { in: query, name: account, schema: { type: array, items: { type: integer } } }
- { in: query, name: ordering, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PlaceInfoLookupRequest'
responses:
'200':
description: Matching PUDO points.
content:
application/json:
schema:
type: array
items: { $ref: '#/components/schemas/PlaceInfoLookupResponseItem' }
'400': { $ref: '#/components/responses/BadRequest' }
'403': { $ref: '#/components/responses/Forbidden' }
/v4/promise/prediction/predict/:
get:
tags: [Promise]
summary: Predict Delivery Date
operationId: predictDelivery
description: >-
Return localized delivery date predictions for a destination,
optionally constrained to a courier, service level, and warehouse.
parameters:
- { in: query, name: account, required: true, schema: { type: integer } }
- { in: query, name: destination_country_iso3, required: true, schema: { type: string } }
- { in: query, name: destination_postal_code, schema: { type: string } }
- { in: query, name: courier, schema: { type: string } }
- { in: query, name: service_level, schema: { type: string } }
- { in: query, name: warehouse, schema: { type: string } }
- { in: query, name: language_iso2, schema: { type: string } }
- { in: query, name: calibration, schema: { type: string, enum: [conservative, balanced, aggressive] } }
- { in: query, name: dispatch_now, schema: { type: boolean } }
- { in: query, name: now_override, schema: { type: string, format: date-time } }
- { in: query, name: draft, schema: { type: boolean } }
responses:
'200':
description: Delivery date predictions.
content:
application/json:
schema:
$ref: '#/components/schemas/PromisePrediction'
'400': { $ref: '#/components/responses/BadRequest' }
/v4/returns/return-registrations/:
get:
tags: [Returns]
summary: List Return Registrations
operationId: listReturnRegistrations
parameters:
- { in: query, name: account, schema: { type: integer } }
- { in: query, name: limit, schema: { type: integer } }
- { in: query, name: offset, schema: { type: integer } }
- { in: query, name: ordering, schema: { type: string } }
responses:
'200':
description: Page of return registrations.
content:
application/json:
schema:
$ref: '#/components/schemas/ReturnRegistrationList'
post:
tags: [Returns]
summary: Create Return Registration
operationId: createReturnRegistration
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ReturnRegistration'
responses:
'201':
description: Created.
content:
application/json:
schema: { $ref: '#/components/schemas/ReturnRegistration' }
'400': { $ref: '#/components/responses/BadRequest' }
/v4/returns/return-registrations/{external_id}/:
get:
tags: [Returns]
summary: Get Return Registration
operationId: getReturnRegistration
parameters:
- { in: path, name: external_id, required: true, schema: { type: string, format: uuid } }
responses:
'200':
description: Return registration.
content:
application/json:
schema: { $ref: '#/components/schemas/ReturnRegistration' }
'404': { $ref: '#/components/responses/NotFound' }
/v4/returns/returns-configurations/:
get:
tags: [Returns]
summary: List Return Configurations
operationId: listReturnConfigurations
parameters:
- { in: query, name: account, schema: { type: integer } }
- { in: query, name: limit, schema: { type: integer } }
- { in: query, name: offset, schema: { type: integer } }
- { in: query, name: ordering, schema: { type: string } }
responses:
'200':
description: Return configuration sets.
content:
application/json:
schema:
type: array
items: { $ref: '#/components/schemas/ReturnConfiguration' }
/v4/returns/returns-configurations/{id}/:
get:
tags: [Returns]
summary: Get Return Configuration
operationId: getReturnConfiguration
parameters:
- { in: path, name: id, required: true, schema: { type: string } }
responses:
'200':
description: Return configuration.
content:
application/json:
schema: { $ref: '#/components/schemas/ReturnConfiguration' }
'404': { $ref: '#/components/responses/NotFound' }
/v4/returns/document-templates/:
get:
tags: [Returns]
summary: List Document Templates
operationId: listDocumentTemplates
description: Document templates used for generating return labels and slips.
parameters:
- { in: query, name: account, schema: { type: integer } }
- { in: query, name: limit, schema: { type: integer } }
- { in: query, name: offset, schema: { type: integer } }
responses:
'200':
description: Document templates.
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties: true
/v4/campaign/evaluate/:
get:
tags: [Campaigns]
summary: Evaluate Campaign Targeting
operationId: evaluateCampaign
parameters:
- { in: query, name: accountId, schema: { type: integer } }
- { in: query, name: campaignId, schema: { type: string } }
- { in: query, name: language, schema: { type: string } }
- { in: query, name: medium, schema: { type: string } }
- { in: query, name: message, schema: { type: string } }
- { in: query, name: orderNumber, schema: { type: string } }
- { in: query, name: preview, schema: { type: boolean } }
- { in: query, name: status, schema: { type: string } }
- { in: query, name: trackingId, schema: { type: string } }
responses:
'200':
description: Evaluated campaign content.
content:
application/json:
schema:
type: object
additionalProperties: true
/v4/campaign/redirect/:
get:
tags: [Campaigns]
summary: Campaign Redirect Analytics
operationId: campaignRedirect
parameters:
- { in: query, name: campaignId, schema: { type: string } }
- { in: query, name: trackingId, schema: { type: string } }
- { in: query, name: eventType, required: true, schema: { type: string } }
- { in: query, name: medium, schema: { type: string } }
- { in: query, name: redirectUrl, schema: { type: string, format: uri } }
- { in: query, name: customerSegmentationId, schema: { type: string } }
- { in: query, name: emailId, schema: { type: string } }
- { in: query, name: contentType, schema: { type: string } }
responses:
'302':
description: Redirect to target URL.
/v4/survey/survey/{id}/:
get:
tags: [Surveys]
summary: Get Survey
operationId: getSurvey
parameters:
- { in: path, name: id, required: true, schema: { type: string, format: uuid } }
responses:
'200':
description: Survey definition.
content:
application/json:
schema: { $ref: '#/components/schemas/PublicSurvey' }
'404': { $ref: '#/components/responses/NotFound' }
/v4/survey/survey/{id}/answer/:
get:
tags: [Surveys]
summary: Get Survey Answer
operationId: getSurveyAnswer
parameters:
- { in: path, name: id, required: true, schema: { type: string, format: uuid } }
- { in: query, name: ref_id, required: true, schema: { type: string } }
- { in: query, name: reference_type, schema: { type: string, enum: [return_registration, tracking] } }
responses:
'200':
description: Survey with prefilled answers.
content:
application/json:
schema: { $ref: '#/components/schemas/PublicSurvey' }
post:
tags: [Surveys]
summary: Submit Survey Answer
operationId: submitSurveyAnswer
parameters:
- { in: path, name: id, required: true, schema: { type: string, format: uuid } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SurveyResponseRequest' }
responses:
'200':
description: Submission accepted.
content:
application/json:
schema: { $ref: '#/components/schemas/SurveyResponseResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
/v4/survey/survey/themes/:
get:
tags: [Surveys]
summary: List Survey Themes
operationId: listSurveyThemes
parameters:
- { in: query, name: default, schema: { type: boolean } }
responses:
'200':
description: Survey theme configurations.
content:
application/json:
schema:
type: object
additionalProperties: true
components:
securitySchemes:
parcellabApiToken:
type: apiKey
in: header
name: Authorization
description: >-
`Authorization: Parcellab-API-Token <base64(account_id:token)>`. App-
generated tokens may instead use the `Bearer <token>` scheme.
responses:
BadRequest:
description: Invalid payload or query parameters.
content:
application/json:
schema: { $ref: '#/components/schemas/ErrorResponse' }
Unauthorized:
description: Missing or invalid API token.
content:
application/json:
schema: { $ref: '#/components/schemas/ErrorResponse' }
Forbidden:
description: Token lacks required permissions.
content:
application/json:
schema: { $ref: '#/components/schemas/ErrorResponse' }
NotFound:
description: Resource not found.
content:
application/json:
schema: { $ref: '#/components/schemas/ErrorResponse' }
schemas:
ErrorResponse:
type: object
properties:
success: { type: boolean, example: false }
message: { type: string }
errors:
type: object
additionalProperties: true
Address:
type: object
properties:
name: { type: string }
street: { type: string }
house_no: { type: string }
city: { type: string }
postal_code: { type: string }
country_iso3: { type: string }
state: { type: string }
phone: { type: string }
email: { type: string, format: email }
LineItem:
type: object
properties:
sku: { type: string }
name: { type: string }
quantity: { type: integer }
price: { type: number }
currency: { type: string }
image_url: { type: string, format: uri }
Mutation:
type: object
properties:
type:
type: string
enum:
- add_tracking
- cancel_tracking
- cancel_order
- change_line_item_quantity
- add_line_item
- replace_line_item
payload:
type: object
additionalProperties: true
OrderUpsertRequest:
type: object
required: [account, order_number]
properties:
account: { type: integer }
order_number: { type: string }
destination_country_iso3: { type: string }
recipient_email: { type: string, format: email }
recipient_name: { type: string }
shipping_address: { $ref: '#/components/schemas/Address' }
articles_order:
type: array
items: { $ref: '#/components/schemas/LineItem' }
mutations:
type: array
items: { $ref: '#/components/schemas/Mutation' }
OrderUpsertResponse:
type: object
properties:
external_id: { type: string, format: uuid }
order_number: { type: string }
mutations:
type: array
items:
type: object
properties:
type: { type: string }
result:
type: object
properties:
success: { type: boolean }
message: { type: string }
errors: { type: object, additionalProperties: true }
warnings:
type: array
items: { type: string }
Checkpoint:
type: object
properties:
timestamp: { type: string, format: date-time }
status: { type: string }
status_details: { type: string }
location: { type: string }
courier: { type: string }
Tracking:
type: object
properties:
tracking_number: { type: string }
courier: { type: string }
status: { type: string }
lifecycle: { type: string }
delivery_estimate: { type: string, format: date-time }
checkpoints:
type: array
items: { $ref: '#/components/schemas/Checkpoint' }
OrderInfo:
type: object
properties:
order_number: { type: string }
client_key: { type: string }
order_date: { type: string, format: date-time }
recipient_name: { type: string }
recipient_email: { type: string, format: email }
destination_country_iso3: { type: string }
trackings:
type: array
items: { $ref: '#/components/schemas/Tracking' }
ShopEvent:
type: object
required: [event_timestamp, event_status]
properties:
event_timestamp: { type: string, format: date-time }
event_status: { type: string }
location: { type: string }
event_details: { type: string }
placeholder_value: { type: string }
courier: { type: string }
tracking_number: { type: string }
account: { type: integer }
reference_number: { type: string }
order_number: { type: string }
PlaceInfoLookupItem:
type: object
properties:
courier: { type: string }
service_level: { type: string }
query: { type: string }
PlaceInfoLookupRequest:
type: object
required: [account, lookups, country_iso3]
properties:
account: { type: integer }
country_iso3: { type: string }
lookups:
type: array
minItems: 1
maxItems: 3
items: { $ref: '#/components/schemas/PlaceInfoLookupItem' }
location:
type: object
properties:
latitude: { type: number }
longitude: { type: number }
external_reference: { type: string }
location_address: { $ref: '#/components/schemas/Address' }
PlaceInfoLookupResponseItem:
type: object
properties:
courier: { type: string }
place_type:
type: string
enum: [default, self-service, partner, store, other]
address: { $ref: '#/components/schemas/Address' }
location:
type: object
properties:
latitude: { type: number }
longitude: { type: number }
opening_hours:
type: object
additionalProperties: true
distance_meters: { type: integer }
services:
type: array
items: { type: string }
phone: { type: string }
website: { type: string, format: uri }
external_reference: { type: string }
PromisePrediction:
type: object
properties:
request_id: { type: string }
success: { type: boolean }
prediction:
type: array
items:
type: object
properties:
courier: { type: string }
service_level: { type: string }
date_min: { type: string, format: date }
date_max: { type: string, format: date }
date_likely: { type: string, format: date }
days_min: { type: integer }
days_max: { type: integer }
days_likely: { type: integer }
cutoff: { type: string, format: date-time }
localized:
type: object
additionalProperties: true
ReturnRegistration:
type: object
required: [account, code, reference, customer_email]
properties:
external_id: { type: string, format: uuid, readOnly: true }
sequence_number: { type: string, readOnly: true }
account: { type: integer }
code: { type: string, maxLength: 255 }
reference: { type: string, maxLength: 255 }
customer_email: { type: string }
customer_address: { $ref: '#/components/schemas/Address' }
status:
type: string
enum:
- created
- submitted
- pending_approval
- pending_label
- approved
- rejected
- cancelled
- closed
- processing_failed
- invalid
order_date: { type: string, format: date-time }
order_delivery_date: { type: string, format: date-time }
order_shipping_date: { type: string, format: date-time }
order_total_amount: { type: number }
order_shipping_amount: { type: number }
order_tax_amount: { type: number }
order_currency: { type: string }
articles_order:
type: array
items: { $ref: '#/components/schemas/LineItem' }
articles_return:
type: array
items: { $ref: '#/components/schemas/LineItem' }
return_labels:
type: array
readOnly: true
items:
type: object
additionalProperties: true
tags:
type: array
items: { type: string }
metadata:
type: object
additionalProperties: true
created_at: { type: string, format: date-time, readOnly: true }
updated_at: { type: string, format: date-time, readOnly: true }
ReturnRegistrationList:
type: object
properties:
count: { type: integer }
next: { type: string, format: uri, nullable: true }
previous: { type: string, format: uri, nullable: true }
results:
type: array
items: { $ref: '#/components/schemas/ReturnRegistration' }
ReturnConfiguration:
type: object
properties:
id: { type: string }
account: { type: integer }
code: { type: string }
name: { type: string }
return_periods:
type: array
items:
type: object
additionalProperties: true
return_reasons:
type: array
items:
type: object
additionalProperties: true
compensation_methods:
type: array
items:
type: object
additionalProperties: true
carrier_options:
type: array
items:
type: object
additionalProperties: true
PublicSurvey:
type: object
properties:
id: { type: string, format: uuid }
name: { type: string }
status: { type: string }
type: { type: string }
surveyUrl: { type: string, format: uri }
config:
type: object
additionalProperties: true
editable: { type: boolean }
SurveyResponseRequest:
type: object
properties:
data:
type: object
additionalProperties: true
is_complete: { type: boolean }
reference_id: { type: string }
reference_type:
type: string
enum: [return_registration, tracking]
SurveyResponseResponse:
type: object
properties:
isComplete: { type: boolean }
detail: { type: string }