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 `. App- generated tokens may instead use the `Bearer ` 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 }