Returns (Phase 3 preview)

Implementation-ready Phase 3 preview for signed return requests, operator review, authoritative routing, idempotent return creation and controlled activation.

Phase 3 contract — implementation-ready preview. The wire contract is
frozen and the SKUU-side receiver, review/routing storage and signed customer
client are implemented and locally proven, including the durable operator
release/resume path. The shared TESTING schema/runtime foundation is installed,
read back and empty, while the receiver, outbound creation and recurring sender
remain disabled. A customer must still implement the two interfaces in this
guide and pass bilateral TESTING conformance before either side enables return
traffic. This is not a customer-traffic or production activation notice.

This guide adds returns to the product, inventory, order and fulfilment
integration. Complete Phases 1 and 2 before implementing these interfaces.
This page is the complete public Phase-3 preview contract. The API Reference
in this portal remains the machine-readable contract for accepted Phase 1 and
Phase 2 endpoints until Phase 3 bilateral acceptance.

Overview

ConnectionDirectionPurpose
return.created webhookCustomer → SKUUSubmit one consumer return request for one original consumer order
POST /returnsSKUU → customerCreate one operator-approved return at the original seller for one seller order and physical fulfilment location

Phase 3 reuses the existing environment credentials:

  • customer-to-SKUU webhooks use the shared HMAC secret;
  • SKUU-to-customer requests use the customer-issued bearer token and the same
    shared HMAC secret; and
  • TESTING and production use separate URLs and credentials.

SKUU's safe defaults are returns.receiver_enabled=false,
returns.creation_enabled=false, and returns.creation_dry_run=true. Code
presence does not enable a customer, environment, receiver, outbound write,
recurring sender or production.

What the customer implements

Before bilateral conformance, the customer prepares exactly two capabilities:

  1. emit a signed return.created event when a consumer requests a return; and
  2. accept signed, bearer-authenticated POST /returns requests idempotently.

The customer also confirms its operational return-routing policy before the
live TESTING gate opens. Physical fulfilment-location IDs are opaque identities;
their numeric values do not imply a return address. A customer may approve one
central destination for several physical locations or a different destination
per location. In either case, every routable physical location must have one
complete, explicitly approved destination in the environment configuration.
SKUU never infers that mapping from the ID, a shop business address or a virtual
network location. Missing or ambiguous routing stays closed for manual review.

Keep event emission and recurring delivery disabled until SKUU explicitly
opens a coordinated TESTING window. Use an existing synthetic Phase-2 order,
never real customer data, for conformance.

Shared request rules

Every body-bearing request uses:

Content-Type: application/json
X-SKUU-Signature: sha256=<lowercase hexadecimal HMAC-SHA256>

Calculate the signature over the exact raw UTF-8 JSON bytes sent on the wire:

HMAC-SHA256(shared_secret, exact_raw_request_body_bytes)

Verify the signature before parsing JSON or performing a side effect. A
transport retry keeps the identical body bytes, signature, idempotency identity
and embedded timestamps.

IDs are opaque, stable strings. Unless a field says otherwise, canonical
text
means a non-empty string with no surrounding whitespace and no ASCII
control characters. Timestamps are RFC 3339 with seconds and an explicit
timezone. Quantities are positive JSON integers from 1 through
2,147,483,647, not strings or deltas. All request objects are closed: do not
add undocumented properties.

1. Send return.created

Send one signed event for one return request. The event may contain multiple
lines, but all lines belong to the same original consumer order.

POST {skuu_webhook_url}
Content-Type: application/json
X-SKUU-Signature: sha256=<hmac>

SKUU supplies the complete environment-specific webhook URL before testing.
Do not derive it or reuse a URL from another environment.

{
  "spec_version": "1",
  "event": "return.created",
  "event_id": "evt_return_01JABC",
  "occurred_at": "2026-09-10T09:00:00Z",
  "data": {
    "return_id": "RET-1001",
    "order_id": "ORD-10045",
    "created_at": "2026-09-10T08:59:50Z",
    "reason": "too_small",
    "resolution": "refund",
    "customer_note": null,
    "lines": [
      {
        "return_line_id": "RET-LINE-1",
        "order_line_id": "LINE-1",
        "variant_id": "V-123-38-BLK",
        "quantity": 1,
        "reason": "too_small"
      }
    ]
  }
}

Envelope fields

FieldTypeRules
spec_versionstringRequired; exactly "1"
eventstringRequired; exactly "return.created"
event_idstringRequired; globally unique logical-event identity, 1–255 canonical characters
occurred_atRFC 3339 timestampRequired; timezone-aware source event time
dataobjectRequired; closed return-request object

Return fields

FieldTypeRules
return_idstringRequired; stable customer-native return identity, unique within the source customer, 1–255 canonical characters
order_idstringRequired; exact original consumer-order identity previously sent in Phase 2, 1–255 canonical path-safe characters; it cannot be . or .. and cannot contain /, \, ?, # or %
created_atRFC 3339 timestampRequired; timezone-aware time at which the return was requested
reasonstringRequired; non-empty canonical request-level reason, maximum 255 characters
resolutionstringRequired; non-empty canonical requested outcome, maximum 64 characters; it does not authorize or execute a refund
customer_notestring or nullOptional; when present, non-empty canonical text, maximum 5,000 characters
linesarrayRequired; 1–1,000 unique return lines

Line fields

FieldTypeRules
return_line_idstringRequired; unique within this return, 1–255 canonical characters
order_line_idstringRequired; exact original consumer-order line identity, unique within this return, 1–255 canonical characters
variant_idstringRequired; exact original customer variant identity for that order line, 1–255 canonical characters
quantityintegerRequired; positive absolute requested quantity from 1 through 2,147,483,647
reasonstringRequired; non-empty canonical line-level reason, maximum 255 characters

Important behavior:

  • SKUU validates every line before writing anything. A rejected line cannot
    leave a partial return.
  • The source customer, order, order line and variant identities must agree.
  • A valid first delivery is stored atomically as pending_review. Intake never
    approves the return, creates a refund, changes an order, writes financial
    records or calls another customer. During later operator review, every line
    must resolve through the original Phase-2 order data to exactly one recorded
    seller-side physical fulfilment location. Zero or multiple matches keep it
    unroutable and prevent approval or outbound creation.
  • The cumulative quantity across pending_review and approved return
    requests cannot exceed the original ordered quantity.
  • event_id plus the SHA-256 hash of the exact signed request body controls
    replay. An exact replay is a duplicate. Reusing an event ID with changed
    bytes is a conflict and creates no second return.
  • Reusing a customer-native return_id for another event is also a conflict.
  • Source timestamps more than five minutes in the future are permanently
    rejected without a write.

SKUU webhook response matrix

HTTPMeaningCustomer action
200The signed delivery was acknowledged. This covers a first valid request, exact replay, disabled receiver, or a permanently invalid/conflicting business request. The body is empty and non-contractual; 200 alone is not proof of a database write.Stop. Use bilateral conformance evidence to distinguish pending_review, duplicate and rejected outcomes.
401HMAC authentication is missing or invalid, or the customer route is unavailable without revealing its existence.Do not retry automatically; correct the credential or signing implementation.
413Raw body exceeds 512 KiB.Do not retry unchanged; reduce the request to the documented contract.
5xxA valid event could not complete durable storage.Retry the identical event ID, body and timestamps with backoff.

The customer sender retries network failures and SKUU 5xx responses with
backoff and stops on every 200. Permanent signed schema or business errors
are acknowledged to prevent an infinite retry loop.

2. Implement POST /returns

Expose one customer-hosted endpoint that creates an approved return for one
original seller order and one physical fulfilment location.

POST {customer_api_root}/returns
Authorization: Bearer <token>
Content-Type: application/json
X-SKUU-Signature: sha256=<hmac>
{
  "external_ref": "skuu-return-<opaque-stable-value>",
  "order_id": "SELLER-ORDER-5001",
  "status": "approved",
  "destination": {
    "name": "Returns Warehouse",
    "address_line1": "Warehouse Street 1",
    "address_line2": null,
    "postal_code": "1000 AA",
    "city": "Amsterdam",
    "country_code": "NL"
  },
  "lines": [
    {
      "order_line_id": "skuu-line-01JABC",
      "variant_id": "SELLER-VARIANT-38-BLK",
      "quantity": 1
    }
  ]
}

Request fields

FieldTypeRules
external_refstringRequired; opaque SKUU idempotency identity, 1–255 canonical characters
order_idstringRequired; exact customer-native seller order created through Phase-2 POST /orders, 1–255 canonical characters
statusstringRequired; exactly "approved"
destinationobjectRequired; closed physical return destination
linesarrayRequired; 1–1,000 unique seller order lines

Destination fields are name (maximum 255 characters), address_line1
(maximum 255), optional address_line2 (maximum 255; it may be omitted or
null), postal_code (maximum 32), city (maximum 100) and an uppercase
two-letter country_code. All strings are non-empty canonical text when
present.

Each line contains the seller-side order_line_id originally supplied as the
line external_ref in Phase-2 POST /orders, the seller-native variant_id
and a positive absolute quantity. Both IDs are 1–255 canonical characters;
the quantity is a JSON integer from 1 through 2,147,483,647. These are
seller identities; they are not the buyer-native IDs from the inbound event.

Return HTTP 200 with exactly this body shape:

{
  "success": true,
  "message": "Successfully created return.",
  "external_ref": "skuu-return-<opaque-stable-value>",
  "return_id": "RET-5001",
  "status": "approved"
}

Important behavior:

  • external_ref is the idempotency key and must be echoed exactly.
  • return_id is the stable customer-native identity of the created return and
    must contain 1–255 canonical characters.
  • An identical replay returns the original return and the identical success
    receipt. It must not create a second return, label, notification or other
    side effect.
  • Reusing an external_ref with a different payload returns HTTP 409 with
    error.code=idempotency_conflict.
  • Unknown order_id or order_line_id returns HTTP 404 without a partial
    return.
  • Only HTTP 200 is a successful create or identical replay. HTTP 201 and
    success bodies with missing, changed or extra fields do not satisfy the v1
    contract.

Customer-hosted response matrix

Errors use the standard closed envelope:

{
  "error": {
    "code": "unknown_order",
    "message": "The supplied order_id does not exist"
  }
}

error.code is stable and machine-readable. error.message is diagnostic
text for operators and must not be used as the programmatic decision key.

HTTPStable code or meaningSKUU action
200Exact five-field success receiptStop and durably record the receipt.
400Permanent request errorDo not retry unchanged; correct the request.
401unauthorizedBearer or HMAC authentication is missing or rejected. Do not retry automatically; correct the credential or signature.
403forbiddenValid credentials do not have access to this operation. Do not retry automatically; correct the access policy.
404unknown_order or unknown_lineDo not retry unchanged; resolve the seller identity.
409idempotency_conflictStop and investigate changed-payload reuse of external_ref.
429Rate limitedRetry identical signed bytes with backoff and honour numeric-seconds Retry-After.
5xxTemporary server failureRetry identical signed bytes with the same external_ref and signature.

SKUU uses a bounded retry policy for network failures, HTTP 429 and HTTP
5xx. Other 4xx responses and invalid success receipts are permanent until
an operator corrects the cause.

Review and routing behavior

One inbound request can span lines fulfilled by different sellers, seller
orders or physical locations. After operator approval, SKUU:

  1. resolves every line to the original seller order, seller line, variant and
    exactly one physical fulfilment location recorded during Phase 2; zero or
    multiple location matches are unroutable and remain for manual review;
  2. rejects same-source loops and any missing, inactive, incomplete, virtual or
    unapproved destination. In customer terms, a line whose original seller is
    the same customer that emitted the return request is not routed back through
    SKUU; Phase 3 outbound creation targets a different SKUU Connect seller;
  3. loads the destination only from the authoritative active physical-location
    directory—never from a virtual SKUU_Network location or a shop YAML or
    business-address fallback. The customer owns the mapping decision: one
    approved central address may be recorded for several physical locations, or
    each location may have its own approved address;
  4. groups lines by seller customer, seller order and physical location;
  5. assigns one deterministic opaque external_ref to every group; and
  6. sends one POST /returns request per group in deterministic order.

The live release seam durably freezes the complete validated JSON request for
every group before the first external call. Replanning the same reviewed return
must reproduce the exact same set of groups, references and bodies; missing,
extra or changed groups fail closed instead of overwriting the plan. Accepted
groups retain their exact customer receipt. A retry skips already accepted
groups and sends only prepared groups with their frozen request bodies.

This is an exactly-once-ish business-effect contract, not a claim that an
HTTP network provides exactly-once delivery. Webhook and outbound transports
may deliver more than once. Stable event/reference identities, frozen bytes,
atomic first-write/conflict checks and exact receipt replay ensure that an
identical retry has one logical effect, while changed-payload reuse fails
closed.

There is deliberately no automatic release from the inbound webhook. An
operator must review the complete request and approve or reject it first. An
identical repeat review is safe; a conflicting second review decision fails
closed.

Dry-run is different from a live release: it validates and builds the complete
plan locally but sends no HTTP request and persists no dispatch plan, frozen
body or receipt.

Operator review and release

This section is for SKUU operators. Customers implement the two wire
interfaces above; they do not run these commands.

Review and release are deliberately separate commands:

skuu returns connect-review --return-id <internal-uuid> --decision approved
skuu returns connect-review --return-id <internal-uuid> --decision rejected
skuu returns connect-release --return-id <internal-uuid>

connect-review records one explicit terminal decision and never performs an
outbound call. connect-release accepts only an approved request, resolves the
target customer from the existing shop configuration, honours the independent
creation gate and dry-run mode, and emits a machine-readable redacted result.
In live mode it freezes the complete dispatch plan before transport; rerunning
the command skips accepted groups and resumes only prepared groups with their
original bytes and signatures. Missing, duplicate or inconsistent target
configuration fails closed.

Testing and activation

SKUU-side automated Phase-3 verification passes the strict inbound/outbound,
replay, conflict, routing, review, dry-run, frozen-plan and durable-resume
matrix.

The Phase-3 persistence/runtime foundation is installed in shared TESTING and
its access-control and empty-baseline readback has passed. This platform
foundation does not activate a customer:
customer implementation and bilateral conformance have not occurred, and
customer event emission, the SKUU receiver, live outbound writes, recurring
delivery and production all remain closed. Safe runtime defaults stay
returns.receiver_enabled=false, returns.creation_enabled=false and
returns.creation_dry_run=true.

The stable OpenAPI companion remains Phase 1 plus Phase 2. Phase 3 stays out of
that machine-readable contract until bilateral acceptance.

Activation proceeds in separate, explicitly approved steps:

  1. Complete and mutually sign off Phases 1 and 2.
  2. Customer implements both Phase-3 interfaces with TESTING credentials while
    event emission remains disabled.
  3. Customer confirms which complete return destination applies to every
    eligible physical fulfilment location; SKUU records only that approved
    mapping and does not infer it from IDs or another address source.
  4. Before the customer window, re-read the installed TESTING schema, service-role
    RPC access and customer-specific empty baseline; stop if any preflight fails.
  5. Keep returns.receiver_enabled=false, returns.creation_enabled=false,
    and returns.creation_dry_run=true until those preflights pass and the
    bounded bilateral window is separately approved.
  6. Run signed inbound first-delivery, exact-replay, changed-payload conflict,
    identity and cumulative-quantity checks using one synthetic Phase-2 order.
  7. Review the stored request manually and prove approval/rejection idempotency.
  8. Prove a dry-run release creates no transport or durable dispatch record.
  9. Open only the bounded live TESTING write gate and prove one grouped
    POST /returns, exact customer replay and durable receipt/resume behavior.
  10. Close the window, verify no unexpected business, financial or production
    effects, and exchange bilateral Phase-3 sign-off.
  11. Enable recurring event delivery and production only in later, separately
    approved cutovers.

Return labels, carrier tracking, warehouse inspection, refund execution,
consumer notifications and cost allocation are outside this Phase-3 preview.
They require a later documented contract revision.


Did this page help you?