Webhook Returns Edit the file on GitHub

Webhook Returns allows Skroutz Merchants to automatically receive return details to their platform when a new return is created or an existing one is updated (its state or logistics change), so the merchant's own system can stay in sync without polling the Returns API.

Webhook Returns is currently under development .

Table of Contents

Setup

In order to be able to use the webhook, a return webhook URL should be registered by the merchant from within Smart Cart settings page in merchant's panel (Merchants > Services > Skroutz Marketplace).

Registering a URL alone does not enable delivery — the return webhook must also be explicitly turned on from the same settings page. Both are required before any request is sent.

Webhook Returns requests are sent from the same infrastructure as Webhook Orders requests, so the same IP ranges apply:

IPv4:

  • 185.6.76.0/22
  • 3.73.204.153/32
  • 3.72.204.195/32
  • 3.67.183.221/32
  • 63.34.193.172/32
  • 54.195.53.34/32
  • 108.129.50.199/32

IPv6:

  • 2a03:e40::/32

Please ensure these IPs are whitelisted in your firewall or security tools to prevent webhook delivery failures.

You can also access the IP ranges in JSON format for programmatic consumption.

The webhook URL should match the shop's domain and it should follow secure HTTP (HTTPS)

Webhook URL example
Shop URL Webhook URL
https://shop.gr https://shop.gr/smart_cart_returns

Webhook requests

An HTTP POST request is sent to the predefined return webhook URL once an event has been triggered.

The anatomy of a request

Request
POST {webhook_url}
Request headers
Header Value
Content-Type application/json; charset=utf-8
User-Agent Skroutz OrderNotifier v1 (shared with Webhook Orders)

Since the User-Agent value is shared with Webhook Orders, it cannot be used to distinguish order from return notifications. Use the event_type field in the request body instead.

Expected request response
200

Webhook events

The available webhook events for which a request is performed are:

  • return created events
  • return updated events

Return created

A return created webhook request (merchant_return_created) is triggered once, right after a return is first placed.

Return updated

A return updated webhook request (merchant_return_updated) is triggered whenever:

  • The return's state changes (e.g. approved by the merchant, marked as returning, returned, rejected, expired or cancelled). If the update also makes shipment information newly available — for example when the return transitions into the returning state — the payload additionally carries the courier and returning_address fields.
  • The return's courier is reassigned on an existing return shipment.
  • The return's courier tracking IDs become available.
  • The deadline of the merchant's review changes, e.g. it is extended after the merchant contacts the customer from the merchant panel. The payload carries the new review.expires_at.

While a return waits for the merchant's review, its payload carries the review and the handle_options to handle it with. Their delivery choices are those available when the request was sent, so a request retried later may list pickup windows that have passed: fetch the return for the current ones.

A return updated request is only sent once a return created request has already been delivered for that same return and webhook URL. In practice, if you enable the return webhook (or change its URL) after a return already exists, that return will not receive update events until a fresh return created event has been recorded against the new URL.

Request payload

Name Type Value Description
event_type String merchant_return_created, merchant_return_updated Return event type
event_time Date String in format
YYYY-MM-DDTHH:MM:SSZ
  Event creation time
return Object   Return details
changes Object   Return changes with old and new values (optional)

Return object

Name Type Values Description
return_code String   Return Code
state String pending_merchant_review, returning, pending_physical_review, pending_service_inspection, returned, rejected, expired, cancelled, resolved_without_return Current lifecycle state of the return. One of the return states.
order_code String   The code of the order this return belongs to
created_at Date String in format
YYYY-MM-DDTHH:MM:SSZ
  Return creation date
courier_tracking_ids Array of Strings (Optional) Deduplicated tracking IDs across current shipments
courier String (Optional) Human-readable name of the courier (e.g. ACS)
returning_address Object (Optional) Returning address — the address the merchant should receive the return at
return_line_items Array   Return line items — the products being returned
review Object (Optional) Review — the review waiting for the merchant
handle_options Array (Optional) Handle options — the ways the merchant can handle the review

courier_tracking_ids, courier and returning_address are omitted entirely (not sent as null) when not applicable — e.g. virtual returns with no shipment.

review and handle_options are present only while the return is in state pending_merchant_review and waits for the merchant's review. They are omitted once the review is handled or its deadline passes.

Return states

The state field is one of the following string values:

State Description
pending_merchant_review The customer submitted a return request and the merchant needs to review it.
returning The package is in transit back to the merchant.
pending_physical_review The package arrived at the merchant and must perform physical inspection.
returned The package was delivered back to the merchant.
rejected The return was rejected.
expired The merchant never responded to the return request within the deadline.
cancelled The return was cancelled.
pending_service_inspection A technician or an authorised service is to inspect the product.
resolved_without_return The merchant sent the customer the missing part, so the product is not returned.

Returning address

Present only when the return has a shipment.

Name Type Description
returning_address.street_name String Street/road name
returning_address.street_number String Building number
returning_address.zip String Postal code
returning_address.city String City
returning_address.region String Region/state
returning_address.country_code String Country code (e.g. GR)

Return line items

Each element of the return_line_items array represents one product line being returned.

Name Type Values Description
id String   ID of the order line item being returned
ean String   EAN code of the product being returned
product_name String   Product display name
returning_quantity Integer   How many units of this product the customer is returning
return_reason String faulty, wrong_product, withdrawal, damaged_product, expired_product, authenticity_doubt, delivery_issues, other (Optional) Reason the customer selected
sub_reason String different_product, missing_line_item, missing_part, wrong_delivered_size, content_mistake, damaged_courier_fault, damaged_merchant_fault (Optional) A more specific reason, e.g. missing_part for a wrong_product return
requested_compensation String refund, replace, repair, gift_card, none, consolation_coupon (Optional) What the customer asked for
user_comment String (Optional) Free-text comment left by the customer explaining the return
user_photos Array of Strings (Optional) Full URLs of photos uploaded by the customer as evidence
user_videos Array (Optional) Videos uploaded by the customer as evidence

User videos

Name Type Description
id String The video ID
url String Watch the video (requires your API token)
thumbnail_url String The video's thumbnail (requires your API token)

Review

Present while the return waits for the merchant's review.

Name Type Values Description
review_type String faulty, missing_part, out_of_policy_withdrawal, unopened_category_withdrawal, out_of_policy_wrong_size, unopened_category_wrong_size Why the return needs the merchant's review
expires_at Date String in ISO 8601 format   Until when the merchant can handle the review. Afterwards Skroutz handles it, and the merchant may lose their right to compensation
holiday_auto_approval Boolean   Whether the withdrawal is out of policy only because of the holiday period, so Skroutz approves it when the deadline passes
customer_conversation_open Boolean   Whether a conversation with the customer about the product is open in the merchant panel

Handle options

The options to send to handle the return: approve, then send_missing_part, then the rejection reasons. Each option resolves the review. Contacting the customer, which only extends the deadline, is available in the merchant panel only.

Name Type Description
option String The value to send as option: approve, send_missing_part or a rejection reason
comment_required Boolean Rejection reasons only: whether comment is required
supports_proposed_part_url Boolean Rejection reasons only, present only when true: whether proposed_part_url can be sent
delivery Object send_missing_part only: the delivery options

Rejection reasons

Review type Rejection reasons
faulty contact_manufacturer (not offered while the product is within the dead on arrival period), usability_suggestions, not_faulty, resolved_via_customer_communication
missing_part part_not_included, not_missing_part, resolved_via_customer_communication
out_of_policy_withdrawal, unopened_category_withdrawal, out_of_policy_wrong_size, unopened_category_wrong_size out_of_policy_withdrawal
Option Meaning
approve The merchant accepts the return
send_missing_part The merchant sends the missing part to the customer with an additional delivery, at the shop's cost, and the product is not returned. Offered for missing_part reviews when the order can get an additional delivery, but not for a product the merchant delivered with their own cargo carrier
contact_manufacturer The customer needs to contact the manufacturer or the authorised service provider
usability_suggestions The product has been used in a way that affects how it works
not_faulty The product is not faulty: it works according to its specifications
part_not_included The product was delivered complete as described: no part is missing. The merchant can point the customer to the part on Skroutz, e.g. when it is sold separately, with proposed_part_url
not_missing_part The product page on Skroutz has wrong content that needs a correction
resolved_via_customer_communication The merchant already contacted the customer and the issue has been resolved
out_of_policy_withdrawal The withdrawal is outside the return policy

Delivery options

The choices for the missing part's delivery, named after the params of send_missing_part, as in an order's accept options.

Name Type Example Description
delivery.pickup_location Array   Pickup locations, the order's own first
delivery.weight Object { "min": 1, "max": 50 } Valid weight range, in whole kilos
delivery.number_of_parcels Array [1, 2, 3] Valid values for number_of_parcels

Delivery option: Pickup location

Name Type Description
pickup_location.id String The location ID to send as pickup_location. The same IDs as in an order's accept options
pickup_location.label String A human readable address
pickup_location.pickup_window Array Pickup windows to send with cargo: false
pickup_location.cargo_pickup_window Array Pickup windows to send with cargo: true. Present only for an order shipped as a cargo item

Delivery option: Pickup window

Name Type Example Description
pickup_window.id String "20261029T1000-20261029T1400" The pickup window ID to send as pickup_window
pickup_window.label String "10:00 - 14:00, Πέμ 29/10/26" A human readable time range

As in an order's accept options, the id identifies the window by its start and end time (YYYYMMDDTHHMM-YYYYMMDDTHHMM, local Greek time). Each window books its own courier, so there is no courier to choose. The same id can appear in both lists of a location, so cargo tells which one you picked.

Return changes object

Only present on return updated requests, and only includes the keys that actually changed.

Field Shape Notes
state { old, new } Raw state values, see return object
courier { old, new } Human-readable courier name; old can be null when courier info first becomes available
returning_address { old, new } Same shape as returning address
courier_tracking_ids { old, new } Only included when a new value is actually present
review_expires_at { old, new } The review's deadline, as in review.expires_at

Payload Examples

Example 1 (return created - waiting for the merchant's review)

{
  "event_type": "merchant_return_created",
  "event_time": "2026-08-18T09:12:03Z",
  "return": {
    "return_code": "R-111111-1111111",
    "state": "pending_merchant_review",
    "order_code": "48213907",
    "created_at": "2026-08-18T09:12:03Z",
    "return_line_items": [
      {
        "id": "gY6oNzr8jp",
        "ean": "1234567890123",
        "product_name": "Apple iPhone 15 128GB",
        "returning_quantity": 1,
        "return_reason": "wrong_product",
        "sub_reason": "missing_part",
        "requested_compensation": "replace",
        "user_comment": "The charging cable was not in the box.",
        "user_photos": [
          "https://api.skroutz.gr/assets/returns/photo_1.jpg"
        ],
        "user_videos": [
          {
            "id": "3f1c9a52d0e84b6f",
            "url": "https://api.skroutz.gr/merchants/ecommerce/returns/R-111111-1111111/videos/3f1c9a52d0e84b6f",
            "thumbnail_url": "https://api.skroutz.gr/merchants/ecommerce/returns/R-111111-1111111/videos/3f1c9a52d0e84b6f/thumbnail"
          }
        ]
      }
    ],
    "review": {
      "review_type": "missing_part",
      "expires_at": "2026-08-19T18:00:00+03:00",
      "holiday_auto_approval": false,
      "customer_conversation_open": false
    },
    "handle_options": [
      { "option": "approve" },
      {
        "option": "send_missing_part",
        "delivery": {
          "pickup_location": [
            {
              "id": "YlpD0KROym",
              "label": "Πανεπιστημίου 2, Τ.Κ. 10564, Αθήνα, Αττική",
              "pickup_window": [
                { "id": "20260819T1000-20260819T1400", "label": "10:00 - 14:00, Τετ 19/08/26" },
                { "id": "20260819T1500-20260819T1800", "label": "15:00 - 18:00, Τετ 19/08/26" }
              ]
            }
          ],
          "weight": { "min": 1, "max": 50 },
          "number_of_parcels": [1, 2, 3]
        }
      },
      { "option": "part_not_included", "comment_required": true, "supports_proposed_part_url": true },
      { "option": "resolved_via_customer_communication", "comment_required": false },
      { "option": "not_missing_part", "comment_required": true }
    ]
  }
}

Example 2 (return updated - shipment info newly available)

{
  "event_type": "merchant_return_updated",
  "event_time": "2026-08-19T10:00:00Z",
  "return": {
    "return_code": "R-111111-1111111",
    "state": "returning",
    "order_code": "48213907",
    "created_at": "2026-08-18T09:12:03Z",
    "courier": "ACS",
    "returning_address": {
      "street_name": "Ermou",
      "street_number": "12",
      "zip": "10563",
      "city": "Athens",
      "region": "Attica",
      "country_code": "GR"
    },
    "return_line_items": [
      { "id": "gY6oNzr8jp", "ean": "1234567890123", "product_name": "Apple iPhone 15 128GB", "returning_quantity": 1 }
    ]
  },
  "changes": {
    "state": { "old": "pending_merchant_review", "new": "returning" },
    "courier": { "old": null, "new": "ACS" },
    "returning_address": {
      "old": null,
      "new": {
        "street_name": "Ermou",
        "street_number": "12",
        "zip": "10563",
        "city": "Athens",
        "region": "Attica",
        "country_code": "GR"
      }
    }
  }
}

Example 3 (return updated - courier tracking IDs become available)

{
  "event_type": "merchant_return_updated",
  "event_time": "2026-08-19T11:30:00Z",
  "return": {
    "return_code": "R-111111-1111111",
    "state": "returning",
    "order_code": "48213907",
    "created_at": "2026-08-18T09:12:03Z",
    "courier": "ACS",
    "courier_tracking_ids": ["ACS1234567890"],
    "returning_address": {
      "street_name": "Ermou",
      "street_number": "12",
      "zip": "10563",
      "city": "Athens",
      "region": "Attica",
      "country_code": "GR"
    },
    "return_line_items": [
      { "id": "gY6oNzr8jp", "ean": "1234567890123", "product_name": "Apple iPhone 15 128GB", "returning_quantity": 1 }
    ]
  },
  "changes": {
    "courier_tracking_ids": { "old": null, "new": ["ACS1234567890"] }
  }
}

Example 4 (return updated - courier reassignment)

{
  "event_type": "merchant_return_updated",
  "event_time": "2026-08-19T12:30:00Z",
  "return": {
    "return_code": "R-111111-1111111",
    "state": "returning",
    "order_code": "48213907",
    "created_at": "2026-08-18T09:12:03Z",
    "courier": "Speedex",
    "courier_tracking_ids": ["ACS1234567890"],
    "returning_address": {
      "street_name": "Ermou",
      "street_number": "12",
      "zip": "10563",
      "city": "Athens",
      "region": "Attica",
      "country_code": "GR"
    },
    "return_line_items": [
      { "id": "gY6oNzr8jp", "ean": "1234567890123", "product_name": "Apple iPhone 15 128GB", "returning_quantity": 1 }
    ]
  },
  "changes": {
    "courier": { "old": "ACS", "new": "Speedex" }
  }
}

Example 5 (return updated - plain state change)

{
  "event_type": "merchant_return_updated",
  "event_time": "2026-08-19T14:03:11Z",
  "return": {
    "return_code": "R-111111-1111111",
    "state": "returned",
    "order_code": "48213907",
    "created_at": "2026-08-18T09:12:03Z",
    "courier": "Speedex",
    "courier_tracking_ids": ["ACS1234567890"],
    "returning_address": {
      "street_name": "Ermou",
      "street_number": "12",
      "zip": "10563",
      "city": "Athens",
      "region": "Attica",
      "country_code": "GR"
    },
    "return_line_items": [
      {
        "id": "gY6oNzr8jp",
        "ean": "1234567890123",
        "product_name": "Apple iPhone 15 128GB",
        "returning_quantity": 1
      }
    ]
  },
  "changes": {
    "state": { "old": "returning", "new": "returned" }
  }
}

Example 6 (return updated - review deadline extended)

The handle_options are shortened here; they are the same as in Example 1.

{
  "event_type": "merchant_return_updated",
  "event_time": "2026-08-18T11:30:00Z",
  "return": {
    "return_code": "R-111111-1111111",
    "state": "pending_merchant_review",
    "order_code": "48213907",
    "created_at": "2026-08-18T09:12:03Z",
    "return_line_items": [
      {
        "id": "gY6oNzr8jp",
        "ean": "1234567890123",
        "product_name": "Apple iPhone 15 128GB",
        "returning_quantity": 1,
        "return_reason": "wrong_product",
        "sub_reason": "missing_part",
        "requested_compensation": "replace"
      }
    ],
    "review": {
      "review_type": "missing_part",
      "expires_at": "2026-08-20T18:00:00+03:00",
      "holiday_auto_approval": false,
      "customer_conversation_open": true
    },
    "handle_options": [
      { "option": "approve" },
      { "option": "part_not_included", "comment_required": true, "supports_proposed_part_url": true }
    ]
  },
  "changes": {
    "review_expires_at": { "old": "2026-08-19T18:00:00+03:00", "new": "2026-08-20T18:00:00+03:00" }
  }
}