Pre-validation

Some shops review a request before accepting it: they look at the items, the reasons and the pictures, approve or decline each unit, sometimes adjust the amount, and only then the shopper ships. This page describes that flow for returns and exchanges; second-life offers and repairs follow the same shape with their own endpoints, described in Second life (Circular) and Repairs.

Does the shop pre-validate?

GET /policies says it: needValidation true means the shop reviews first. userAcceptation true means the shop also asks the shopper to confirm the decision (typically because amounts can change); when it is false the shopper still completes the shipping, but cannot reject what the shop approved.

Read needValidation before creating: POST /returns/create on a shop that pre-validates is not blocked and skips the review entirely.

1. The request

POST /returns/request?lang=en
Content-Type: application/json

{
  "items": [
    { "id": "14577068736858", "fulfillmentId": "5294120468773", "items": [ { "fulfillmentId": "5294120468773", "reasonId": "9e09f0f3-55bd-4be9-ab86-971eeb773ded", "customerInfo": "It is too small" } ] }
  ],
  "termsAndConditionsAcceptance": true
}

No address, shipping or refund method yet. The response is the return with preValidationStatus and userPreValidationStatus set to Pending, includeUserPreValidation telling whether the shopper will have a say, and needLabel true. The units are reserved: they are no longer quantityAvailable on the order. Calling this endpoint on a shop without pre-validation answers 400 Return request is not enabled. The same eligibility rules as the direct creation apply (windows, blacklist, quantities, limits per order).

2. The review

The shop decides from its dashboard. Per unit it sets validationStatus (Accepted or Rejected), a note in validationReasonInfo when it declines, and possibly a new amount (items[].price); on the return it sets preValidationStatus and an optional merchantPreValidationMessage. Nothing else changes until the shopper answers, so there is nothing to poll for except preValidationStatus.

3. The shopper is notified

The shop sends the shopper an email with a link to the portal. The link carries a signed token and the identifier of the return; from an integration, exchange them for a session with POST /auth:

POST /auth
Content-Type: application/json

{ "mode": "Returns", "token": "<token of the link>", "internalId": "44891408138533" }

The session it opens is scoped to that order, like a normal login. Like the OTP login of the other modes, /auth accepts the partner API key, which identifies the caller by itself; without it the call must come from a browser on a Drelife portal of the shop (Origin or Referer header: 401 ApiKeyRequired when there is neither, 400 Domain is not allowed from any other site). It accepts twenty calls per minute per IP and return. Then read the decision:

GET /returns/44891408138533/token

It answers the return prepared for the decision screen: preValidationStatus, merchantPreValidationMessage, includeUserPreValidation, and the items with id (the identifier of the return unit, the one the next call expects), validationStatus, validationReasonInfo and price.

4. The shopper answers

Accept or reject the approved units and complete the shipping:

POST /returns/44891408138533/validate?lang=en
Content-Type: application/json

{
  "accept": [ { "itemId": "d38fce81-37b6-419c-8fb7-ba2f55096396" } ],
  "reject": [ { "itemId": "e49a0f22-...", "reasonInfo": "The new amount is too low" } ],
  "methodId": "fdba82c7-abd2-441f-9498-15227cfa0514",
  "shippingMethodId": "BNS_PCL",
  "shippingType": "DropOff",
  "paymentMethod": "CreditCard",
  "contact": { "firstName": "Jane", "lastName": "Doe", "address1": "Calle Mayor 1", "city": "Madrid", "zip": "28013", "countryCode": "ES", "provinceCode": "M", "phone": "+34600000000" }
}

Rules:

  • Every unit the shop approved must appear in accept or reject; units the shop declined are not decided by the shopper.
  • When includeUserPreValidation is false, reject must be empty and every approved unit must be accepted.
  • The shipping (methodId, shippingMethodId, shippingType, desiredPickUp for pick ups) and the refund method (paymentMethod, optional; when omitted the return keeps CreditCard, a refund to the original payment) are given here, since the request had none. contact is optional and defaults to the address of the return. When the shop handles the shipping itself (withoutLabel true on the return), the shipping fields are not needed.
  • Accepting no unit marks the return as rejected by the shopper; the reserved units go back to the order.

Or reject the whole decision, with no body:

POST /returns/44891408138533/reject

Both calls answer the updated return. After an acceptance the label and, for exchanges with a price difference, the payment link are generated asynchronously, as in a direct creation. userPreValidationStatus becomes Accepted or Rejected and the return proceeds as any other; follow it as described in Follow a return.

Errors of the decision calls

HTTPerrorCodeMessageMeaning
400BadRequestReturn request is not enabledThe shop does not pre-validate
400BadRequestReturn is not pre-validatedThe shop has not approved the return yet, or declined it
400BadRequestReturn already validated by userThe decision was already sent (also for returns created with /returns/create)
400BadRequestReturn does not allow user rejectionreject sent while includeUserPreValidation is false
400BadRequestTrying to accept an item not approved / Trying to reject an item not approvedThe unit was declined by the shop or does not exist
400BadRequestDuplicated item in accept list / Duplicated item in reject list / Item cannot be both accepted and rejectedInconsistent lists
400BadRequestMissing decision for approved item {id}An approved unit is in neither list
400BadRequestAll approved items must be acceptedPartial acceptance when the shopper cannot reject
400BadRequestNo decisions providedBoth lists empty
400BadRequestShipping method not found / Address not found / Marketplace address not foundMissing shipping or address when the return needs a label; the last one is a configuration problem of the shop
405OrderLockedOrderLockedAnother operation on the order is in progress; retry in a few seconds
404NotFoundNot foundUnknown return for this session

Did this page help you?