Skip to main content

From a Sandbox key to a completed return

Start with the API quickstart. Use one dedicated Sandbox project for these recipes. Alkax records physical delivery and return progress. Your commerce system owns refunds, stock, exchanges and customer credit.

Credentials and environments​

The API host is https://api.alkax.io. Sandbox versus Production is selected by the credential's environment, not by a URL path. Never put a Developer key in browser or mobile code. An Alkax account access token is different from an X-Alkax-Key credential.

OperationScope
Create a shipment or canonical returndelivery:create
Read private shipment/return statedelivery:read
Submit delivery/return events; record drop-off receiptdelivery:events
Submit proof or return proof assetsdelivery:proof
Address confirmation, approve/reject/cancel a canonical return, pickup access, RTS resolutiondelivery:write

A complete delivery and return integration needs the scopes required by the operations it performs. Rotation retains the previous key's scopes, so issuing a new key does not change the authorized scope set. A missing proof scope can prevent the dependent completion event from succeeding. Copy only the raw key. See troubleshooting.

Outbound lifecycle​

After address confirmation, use the confirmed immutable snapshot as destination in POST /api/v1/deliveries. Supply an Idempotency-Key and stable activationEventId. Creation returns id, trackingNumber and state. Do not assume the external order reference is an Alkax tracking number.

Submit POST /api/v1/deliveries/{id}/events with a stable UUID eventId, a real occurredAt timestamp and one of these commands:

CommandResult
MarkInTransitInTransit
MarkAtLocalDepotAtLocalDepot
MarkOutForDeliveryOutForDelivery
RecordDeliveryAttemptDeliveryAttempted
CompleteDeliveryDelivered

Retry the exact event after a transport failure. A 409 needs inspection of canonical state; do not invent a new ID to defeat conflict checks. Timestamps more than five minutes into the future are rejected. Event IDs are separate from request IDs used for diagnostics. Do not rely on localized error sentences.

For outbound proof, first POST /api/v1/deliveries/{id}/proofs with stable proofId, method, occurredAt, and the required receiver/reference fields. Supply this proofId to CompleteDelivery. Submit proof before the dependent event. Proof must belong to the same shipment/environment; return proof is a separate contract.

Recipient access​

Anonymous tracking exposes coarse progress only. A tracking number cannot authorize account linking, return requests, private instructions or proof access. Account linking verifies recipient contact. Matching an unverified email string is not an authorization mechanism. Address-confirmation contact is not automatically the canonical shipment's recipient contact.

A linked recipient can request a return only after the shipment is Delivered. In My deliveries, choose pickup or drop-off and submit a reason. The request remains pending until it is approved or rejected. An approved drop-off still requires physical receipt to be recorded. One request is supported per outbound parcel, and decisions are final.

Merchant return authorization​

POST /api/v1/returns accepts originalShipmentId, eventId, type, reason, destination, optional origin/instructions and pickup/receipt proof requirements. Use type: RecipientReturn, reason: RecipientChangedMind for the minimal customer flow. A customer return requires a Delivered outbound shipment. Omitted origin starts from the outbound snapshot, not from a mutable address lookup.

Authorization is separate from logistics. Requested customer returns need POST /api/v1/returns/{id}/approve?eventId={uuid}. Reject and cancel use the same query-ID convention. Cancel is limited to before physical handover. An approved return starts at AwaitingHandover; approval itself does not schedule a courier.

Confirm pickup and submit return proof​

  1. Call POST /api/v1/returns/{id}/pickup-confirmation with delivery:write.
  2. Deliver the returned recipient URL securely. Issuing a replacement revokes the previous uncompleted link. Do not log or expose its token in public tracking.
  3. The recipient reviews/corrects the pickup through the public token flow. The confirmed snapshot stays separate from the original outbound destination.
  4. If evidence is required, capture an actual PNG signature/photo. Upload using PUT /api/v1/returns/{id}/proof-assets/{proofId}/signature (or /photo) with { "dataUrl": "data:image/png;base64,..." }. Maximum 2 MB, 2048 by 2048 pixels.
  5. Use the returned reference in POST /api/v1/returns/{id}/proofs with the same proofId, purpose: Pickup or Receipt, method and timestamp. Signature methods require receiver information. Arbitrary text or merchant URLs are not valid substitutes for uploaded return assets.
  6. Include that proof ID in the corresponding handover/completion event.

Asset retries must use identical bytes. A return's pickup proof cannot satisfy its receipt requirement, and neither can reuse outbound proof. Private assets require delivery:proof and matching project/environment on read as well as write.

Reverse logistics and failed-delivery RTS​

Submit return events with stable IDs to /api/v1/returns/{id}/events: SchedulePickup, MarkPickedUp, MarkAtReturnHub, MarkInTransit, Complete. Complete produces DeliveredToMerchant for a customer return and ReturnedToSender for failed delivery. RecordException records a logistics exception; it is not permission to rewrite history.

For a DeliveryAttempted shipment, call POST /api/v1/deliveries/{id}/resolution with stable evaluationId, normalized failureReason, positive attemptCount, and a confirmed returnDestination when RTS is possible. The documented policy chooses RTS for refusal, recipient unavailable after three attempts, or payment issue after two. Address issues need correction; unknown failures go to manual review. Repeated normalized evidence is deduplicated. Do not pass raw carrier failure text as a canonical reason.

Private return reads use /api/v1/returns/{id} or /by-tracking/{trackingNumber}. Anonymous /api/public/returns/{trackingNumber} omits contact, precise location, instructions and proof.

Responsibility and trust boundaries​

Merchant server -- scoped environment key --> Alkax API
Recipient -- expiring capability ----> Confirm address / pickup
Recipient -- verified account -------> Linked delivery / return request
Public viewer -- tracking number --------> Coarse progress only
Alkax webhook -- signed raw body --------> Merchant webhook receiver
Merchant system -- own business policy ---> Refund / inventory system

Sandbox and Production have separate credentials, resources and webhook subscriptions. A webhook does not transfer permission to another environment. See the webhook cookbook and go-live checklist.

Use the Sandbox test matrix for correction, expiry, rejection, wrong-scope and replay cases.