openapi: 3.1.0
info:
  title: Webhooks
  version: 3.0.0
  description: |-
    Sendcloud uses webhooks to notify your application of parcel updates, such as changes in delivery status.

    > **Important:** Webhooks are scoped to the integration they are configured on. You'll only receive webhook events for parcels created through this integration, and for actions that belong to it. If you have multiple integrations, each one needs its own webhook configuration.

    **To receive the parcel data for every update to a parcel, you need to:**
    - In the Sendcloud platform, go to **Settings** > [**Integrations**](https://app.sendcloud.com/v2/settings/integrations/manage), and click **Configure** on your Sendcloud API integration.
    - Select the **Webhook feedback enabled** checkbox.
    - In the **Webhook url** field, enter the URL of the endpoint in your application that will process the data.
    - Click **Save**.
    - Optional: to check your setup, click **Test API webhook** to send a test webhook to your application.

    Sendcloud signs every webhook request using an HMAC (Hash-based Message Authentication Code) signature with the SHA-256 algorithm. It uses the **Secret Key** or the **Webhook Signature Key** as the secret, depending on your integration type. To check that a webhook came from Sendcloud, compute the HMAC-SHA256 over the entire raw request body, exactly as received and before any parsing, using your secret. Then compare the hex-encoded result with the value of the `Sendcloud-Signature` header.

    ```php
    <?php
    $secret_key = "secretkey";
    // Use the raw request body; don't use $_POST or re-encoded JSON.
    $payload = file_get_contents('php://input');
    $received_signature = $_SERVER['HTTP_SENDCLOUD_SIGNATURE'] ?? '';

    $expected_signature = hash_hmac('sha256', $payload, $secret_key);

    if (!hash_equals($expected_signature, $received_signature)) {
        http_response_code(401);
        exit;
    }

    // Example: for the body {"key": "value"} and secret "secretkey",
    // the signature is 1eed4b3d41f4653ac64fd56f1bf1cbfd349e4482cbc11dff7134bd93e5da4b0a
    ```

    ```python
    import hmac
    import hashlib

    def is_valid_signature(raw_body: bytes, received_signature: str, secret_key: str) -> bool:
        # Hash the raw request body exactly as received; don't parse and re-serialize it.
        expected = hmac.new(secret_key.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
        return hmac.compare_digest(expected, received_signature)

    # Example: for the body {"key": "value"} and secret "secretkey",
    # the signature is 1eed4b3d41f4653ac64fd56f1bf1cbfd349e4482cbc11dff7134bd93e5da4b0a
    assert is_valid_signature(
        b'{"key": "value"}',
        "1eed4b3d41f4653ac64fd56f1bf1cbfd349e4482cbc11dff7134bd93e5da4b0a",
        "secretkey",
    )
    ```

    **Additional notes:**
    - The data your application receives is the same as the parcel payload described in the [Parcel status changed](/api/v3/webhooks/parcel-status-changed) webhook reference.
    - Your endpoint must respond with a `2xx` status code within 10 seconds. If a delivery fails because of a temporary problem, Sendcloud retries it. See [Retry behavior](/api/v3/webhooks#retry-behavior) for details.
    - Webhooks can arrive out of order, for example if your application was unreachable for a while. Use the `timestamp` field in each payload to find the most recent update.
    - For return parcels, you'll only receive webhook updates if the outgoing shipment was created through the API integration.
  contact:
    name: Sendcloud API Support
    url: https://www.sendcloud.dev
    email: contact@sendcloud.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
  - url: https://www.shop_url.com/webhook
    description: User API endpoint
security:
  - Sendcloud-Signature: []
tags:
  - name: Webhooks
paths: {}
webhooks:
  IntegrationConnected:
    post:
      operationId: sc-public-v3-webhooks-integration_connected
      summary: Integration connected
      description: A request is sent to the defined webhook whenever the integration is created within our system.
      x-mint:
        href: /api/v3/webhooks/integration-connected
      tags:
        - Webhooks
      requestBody:
        description: Webhook data you will receive
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IntegrationConnectedWebhook'
      responses:
        '200':
          $ref: '#/components/responses/200'
  IntegrationDeleted:
    post:
      operationId: sc-public-v3-webhooks-integration_deleted
      summary: Integration deleted
      description: A request is sent to the defined webhook whenever the integration is deleted from our system.
      x-mint:
        href: /api/v3/webhooks/integration-deleted
      tags:
        - Webhooks
      requestBody:
        description: Webhook data you will receive
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IntegrationDeletedWebhook'
      responses:
        '200':
          $ref: '#/components/responses/200'
  IntegrationModified:
    post:
      operationId: sc-public-v3-webhooks-integration_modified
      summary: Integration modified
      description: A request is sent to the defined webhook whenever the integration is updated.
      x-mint:
        href: /api/v3/webhooks/integration-modified
      tags:
        - Webhooks
      requestBody:
        description: Webhook data you will receive
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IntegrationUpdatedWebhook'
      responses:
        '200':
          $ref: '#/components/responses/200'
  ParcelStatusChanged:
    post:
      operationId: sc-public-v3-webhooks-parcel_status_changed
      summary: Parcel status changed
      description: Happens whenever a parcel belonging to this integration shifts to a different status. Only parcels created through this specific integration will trigger this webhook.
      x-mint:
        href: /api/v3/webhooks/parcel-status-changed
      tags:
        - Webhooks
      requestBody:
        description: Webhook data you will receive
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ParcelStatusChangedWebhook'
      responses:
        '200':
          $ref: '#/components/responses/200'
  ReturnCreated:
    post:
      operationId: sc-public-v3-webhooks-return_created
      summary: Return created
      description: Happens whenever a return is created from a parcel matching the integration.
      x-mint:
        href: /api/v3/webhooks/return-created
      tags:
        - Webhooks
      requestBody:
        description: Webhook data you will receive
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReturnCreatedWebhook'
      responses:
        '200':
          $ref: '#/components/responses/200'
components:
  securitySchemes:
    Sendcloud-Signature:
      name: Sendcloud-Signature
      type: apiKey
      in: header
    OAuth2ClientCreds:
      type: oauth2
      description: OAuth2 is a standardized protocol for authorization that allows users to share their private resources stored on one site with another site without having to provide their credentials. OAuth2 Client Credentials Grant workflow. This workflow is typically used for server-to-server interactions that require authorization to access specific resources.
      flows:
        clientCredentials:
          tokenUrl: https://account.sendcloud.com/oauth2/token/
          scopes:
            read:analytics: View your shipping analytics
            read:audit-log: View your account's audit log
            read:brand: View your brands
            write:brand: Manage your brands
            write:carrier: Configure carriers and contracts
            read:checkout: View your dynamic checkout configurations and templates
            read:event-subscription: View your event subscriptions
            write:event-subscription: Create and manage your event subscriptions
            read:integration: View your integrations
            write:integration: Connect and manage integrations
            read:invoice: View your invoices
            read:notification: View your notifications
            write:notification: Manage your notifications
            read:operational-settings: View your warehouses, shipping lanes, and other operational settings
            write:operational-settings: Manage your warehouses, shipping lanes, and other operational settings
            read:order: View your orders
            write:order: Import and process your orders
            read:organization: View organization settings
            write:organization: Change organization settings
            read:parcel: View your shipments and their tracking status
            write:parcel: Create, announce, and cancel shipments
            read:pickup: View carrier pickups and the options available for scheduling them
            write:pickup: Schedule and manage carrier pickups
            read:price: View shipping prices
            write:product: Manage your product catalog
            read:return: View your returns
            write:return: Create and manage returns
            read:return-settings: View your return settings
            write:return-settings: Configure your return settings
            read:service-point: View carrier service points
            read:shipping-method: View shipping methods, products and prices
            read:shipping-rule: View your shipping rules
            write:shipping-rule: Create and manage shipping rules
            read:support-ticket: View your support tickets
            write:support-ticket: Manage your support tickets
            read:tracking-message: View your tracking notifications
            write:tracking-message: Manage your tracking notifications
            read:tracking-page: View your tracking page
            write:tracking-page: Customize your tracking page
            read:user: Read your basic account information
  schemas:
    IntegrationWebhookBase:
      description: Base schema for integration webhook payloads
      type: object
      properties:
        action:
          type: string
          description: Describes the webhook action
        timestamp:
          type: integer
          example: 1525271885993
        integration:
          type: object
          properties:
            id:
              type: integer
              format: int64
              example: 1
              minimum: 1
              description: A unique identifier for an integration within Sendcloud
            shop_name:
              type: string
              example: API Integration
              description: The integration name as configured under the [integration settings in Sendcloud](https://app.sendcloud.com/v2/settings/integrations/manage)
            shop_url:
              type: string
              format: uri
              example: https://www.sendcloud.com
              description: The integration url
            system:
              type: string
              example: api
              description: The integration type
            failing_since:
              type:
                - 'null'
                - string
              format: date-time
              example: '2019-02-03T06:48:07Z'
              description: A date time indicating when in time Sendcloud lost connection to the integration.
            last_fetch:
              type:
                - 'null'
                - string
              example: '2019-02-03T06:48:07Z'
              format: date-time
              description: A date time indicating when orders were last fetched successfully.
            last_updated_at:
              type:
                - 'null'
                - string
              format: date-time
              example: '2019-02-03T06:48:07Z'
              description: A date time indicating when the integration settings were updated.
            service_point_enabled:
              type: boolean
              description: True if you have configured [service point](https://support.sendcloud.com/hc/en-us/articles/360026097951-FAQ-Service-Points) support for your integration.
            service_point_carriers:
              type: array
              uniqueItems: true
              description: The service point carriers configured for your integration
              items:
                type: string
            webhook_active:
              type: boolean
              description: True if you have enabled webhooks, False otherwise
            webhook_url:
              type: string
              description: Your integration URL to be used by Sendcloud to communicate with.
              format: uri
              example: https://www.sendcloud.com/sendcloud-webhooks
      required:
        - action
        - timestamp
    IntegrationConnectedWebhook:
      description: The webhook payload when an integration is added to Sendcloud
      type: object
      title: Webhook Integration Connected Object
      allOf:
        - $ref: '#/components/schemas/IntegrationWebhookBase'
        - type: object
          properties:
            action:
              type: string
              example: integration_connected
              enum:
                - integration_connected
    IntegrationDeletedWebhook:
      description: The webhook payload when an integration is deleted from Sendcloud
      type: object
      title: Webhook Integration Deleted Object
      allOf:
        - $ref: '#/components/schemas/IntegrationWebhookBase'
        - type: object
          properties:
            action:
              type: string
              example: integration_deleted
              enum:
                - integration_deleted
    IntegrationUpdatedWebhook:
      description: The webhook payload when an integration is updated in Sendcloud
      type: object
      title: Webhook Integration Updated Object
      allOf:
        - $ref: '#/components/schemas/IntegrationWebhookBase'
        - type: object
          properties:
            action:
              type: string
              example: integration_updated
              enum:
                - integration_updated
    ParcelStatusChangedWebhook:
      type: object
      description: The webhook payload when a parcel (either an outgoing or an incoming one) changes status.
      title: Webhook Parcel Status Changed Object
      properties:
        action:
          type: string
          description: Describes the webhook action
          example: parcel_status_changed
          enum:
            - parcel_status_changed
        timestamp:
          type: number
          description: A unix timestamp indicating the time that the status changed
        carrier_status_change_timestamp:
          type:
            - number
            - 'null'
          description: A unix timestamp indicating the time that the status changed in the carrier's system
        parcel:
          type: object
          description: Parcel object
          properties:
            id:
              type: integer
              description: Sendcloud unique identifier of the parcel
              example: 1
            name:
              type: string
              description: Sender name
              example: Mr Bob
            company_name:
              type: string
              description: Company name of the sender
              example: Sendcloud
            address:
              type: string
              description: Address of the sender
              example: Stadhuisplein 10
            address_divided:
              type: object
              description: Divided object of address
              properties:
                street:
                  type: string
                  description: Street name
                  example: Stadhuisplein
                house_number:
                  type: integer
                  description: House number
                  example: 10
            city:
              type: string
              description: City name
              example: Eindhoven
            postal_code:
              type: string
              description: Postal code
              example: 5611 EM
            telephone:
              type: string
              description: Telephone number of the contact person
              example: '612345678'
            email:
              type: string
              format: email
              description: An email address of the person this parcel is supposed to be delivered to
              example: contact@sendcloud.com
            date_created:
              type: string
              description: Date and time of when the parcel was created, in `DD-MM-YYYY HH:MM:SS` format (UTC).
              example: 03-02-2019 06:48:07
            tracking_number:
              type: string
              description: Tracking number of the shipment
              example: 3SYZXG132912330
            weight:
              type: string
              description: Weight of the parcel
              example: '2.000'
            label:
              type: object
              description: |-
                Labels array. More information in <a
                    href="https://www.sendcloud.com/shipping-label/" target="_blank">Labels</a>
              properties:
                normal_printer:
                  type: array
                  items:
                    type: string
                    format: uri
                    example: https://panel.sendcloud.sc/api/v2/label/normal_printer/3172?start_from=0&hash=bbfd669ee9ebb19408b85b33d181a50040fd9bc4
                label_printer:
                  type: string
                  format: uri
                  example: https://panel.sendcloud.sc/api/v2/label/label_printer/3172?hash=bbfd669ee9ebb19408b85b33d181a50040fd9bc4
            customs_declaration:
              type: object
              description: An object with available printers that lists available links to the created customs declaration form. (deprecated in favor of documents)
            status:
              type: object
              description: |-
                An object containing the ID and the description of the parcel status.

                This object doesn't include a status `code`. Use the `id` to identify the status. You can find all status IDs with the [Retrieve a list of parcel statuses](/api/v2/parcel-statuses/retrieve-a-list-of-parcel-statuses) endpoint.
              properties:
                id:
                  type: integer
                  example: 1
                  description: The Sendcloud unique identifier of the status
                message:
                  type: string
                  example: Ready to send
                  description: The description of the status
            data:
              type: object
              description: A pakjegemak key is still supported within this object, but it is not recommended to use. Please use `to_service_point` property to use service points.
            country:
              type: object
              description: Country of the recipient
              properties:
                iso_3:
                  type: string
                  example: NLD
                iso_2:
                  type: string
                  example: NL
                name:
                  type: string
                  example: Netherlands
            shipment:
              type: object
              description: Shipping method object for a parcel
              properties:
                id:
                  type: integer
                  example: 1
                  description: The unique identifier of the shipping method
                name:
                  type: string
                  example: PostNL Standard
                  description: The Sendcloud shipping method name
            order_number:
              type: string
              description: Order number of your order
              example: ORD12334
            shipment_uuid:
              type: string
              description: Unique identifier that we assign to your shipment within the Sendcloud system.
              example: 87e18823-016b-479b-b9e0-c5c0c4065452
            external_order_id:
              type: string
              description: Our system will ensure uniqueness of shipments with the combination of `external_order_id` and `external_shipment_id`
              example: AMZ23311
            external_shipment_id:
              type: string
              description: Our system will ensure uniqueness of shipments with the combination of `external_order_id` and `external_shipment_id`
              example: AMZ231231
            tracking_url:
              type:
                - string
                - 'null'
              format: uri
              description: The URL where the recipient can track the parcel.
              example: https://tracking.eu-central-1-0.sendcloud.sc/forward?carrier=postnl&code=3SYZXG132912330&destination=NL&lang=en-us&source=NL&type=parcel&verification=5611+AB
            delivery_dates:
              $ref: '#/components/schemas/delivery-dates'
              description: The planned handover and delivery dates of the parcel, in ISO 8601 format (UTC). This is `null` when neither date is set.
              example:
                handover_at: '2026-09-25T10:00:00Z'
                deliver_at: null
            carrier:
              type:
                - object
                - 'null'
              description: The carrier that handles the parcel.
              properties:
                id:
                  type: 'null'
                  description: Always `null`. This field is reserved.
                code:
                  type: string
                  description: The carrier code.
                  example: postnl
                name:
                  type: string
                  description: The carrier name.
                  example: PostNL
                servicepoints_carrier_code:
                  type: string
                  description: The carrier code used for this carrier's service points.
                  example: postnl
            is_return:
              type: boolean
              description: Whether the parcel is a return parcel.
              example: false
            date_updated:
              type: string
              description: Date and time of when the parcel was last updated, in `DD-MM-YYYY HH:MM:SS` format (UTC).
              example: 03-02-2019 06:48:07
            date_announced:
              type:
                - string
                - 'null'
              description: Date and time of when the parcel was announced to the carrier, in `DD-MM-YYYY HH:MM:SS` format (UTC).
              example: 03-02-2019 06:50:12
            colli_uuid:
              type:
                - string
                - 'null'
              format: uuid
              description: The unique identifier shared by all parcels of a multicollo shipment.
              example: d451ccef-1f1a-43a9-afd1-34bb13004700
            collo_nr:
              type: integer
              description: The position of the parcel within a multicollo shipment, starting from `0`. For example, the second of three parcels has a `collo_nr` of `1`.
              example: 0
            collo_count:
              type: integer
              description: The number of parcels in the shipment.
              example: 1
    ReturnCreatedWebhook:
      title: Webhook Return Created Object
      type: object
      description: |-
        The webhook payload when a return is created. This is emitted when a return is created either via the API or the Return Portal.

        Creating a return manually via Return Form does NOT trigger the webhook.
      properties:
        action:
          type: string
          description: Describes webhook action
          example: return_created
          enum:
            - return_created
        timestamp:
          type: number
          description: Unix timestamp
        data:
          type: object
          description: Information about the return
          required:
            - id
          properties:
            id:
              type: number
              description: The id of the return
              example: 42
            brand_id:
              type: integer
            order_number:
              type: string
            return_reason_id:
              type: integer
            return_address_id:
              type: integer
            paid_return:
              type: boolean
            delivery_choice:
              type: string
            refund_type:
              type: string
            items:
              type: array
              description: List of items for this return
              items:
                type: object
                properties:
                  item_id:
                    type: string
                  description:
                    type: string
                  quantity:
                    type: integer
                  sku:
                    type: string
                  hs_code:
                    type: string
                  return_reason_id:
                    type: integer
                required:
                  - quantity
      required:
        - action
        - timestamp
        - data
    delivery-dates:
      title: Delivery Dates
      description: Defined delivery dates
      type:
        - object
      properties:
        handover_at:
          type:
            - string
            - 'null'
          format: date-time
          description: The date when the item will be handed over to the carrier by the merchant in ISO 8601
          example: '2025-02-27T10:00:00.555309+00:00'
        deliver_at:
          type:
            - string
            - 'null'
          format: date-time
          description: The date when the order should reach the end customer in ISO 8601
          example: '2025-03-15T10:00:00.555309+00:00'
  responses:
    '200':
      description: Return a 200 status to indicate that the data was processed successfully. The response body may contain the extended line item.
