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.
| Operation | Scope |
|---|---|
| Create a shipment or canonical return | delivery:create |
| Read private shipment/return state | delivery:read |
| Submit delivery/return events; record drop-off receipt | delivery:events |
| Submit proof or return proof assets | delivery:proof |
| Address confirmation, approve/reject/cancel a canonical return, pickup access, RTS resolution | delivery: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:
| Command | Result |
|---|---|
MarkInTransit | InTransit |
MarkAtLocalDepot | AtLocalDepot |
MarkOutForDelivery | OutForDelivery |
RecordDeliveryAttempt | DeliveryAttempted |
CompleteDelivery | Delivered |
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
- Call
POST /api/v1/returns/{id}/pickup-confirmationwithdelivery:write. - Deliver the returned recipient URL securely. Issuing a replacement revokes the previous uncompleted link. Do not log or expose its token in public tracking.
- The recipient reviews/corrects the pickup through the public token flow. The confirmed snapshot stays separate from the original outbound destination.
- 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. - Use the returned
referenceinPOST /api/v1/returns/{id}/proofswith the sameproofId,purpose: PickuporReceipt, method and timestamp. Signature methods require receiver information. Arbitrary text or merchant URLs are not valid substitutes for uploaded return assets. - 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.