Aramex is the Middle East and South Asia express carrier, headquartered in Dubai and listed in Dubai, and it is the carrier an Indian D2C brand reaches for when the destination is the Gulf. For a commerce database it is a carrier connector: no orders, no listings, no stock. What it gives us is a rate before we book, an AWB and a label when we book, a pickup GUID, an update by update tracking history, and address serviceability checks. Its API is the oldest design in this group: a WCF web service from the Microsoft .NET era, published as SOAP over WSDL, with a JSON mirror of the same operations on the same hosts for callers who would rather not build SOAP envelopes. Both accept exactly the same object graph, so this page treats them as one API with two wire formats.
At a glance
aramex.com returned 403 to an unauthenticated fetcher on 2026-09-21, including the developers solutions center and the Shipping Services API manual PDF. The live WSDL documents on ws.aramex.net are public and were fetched and parsed directly, so every operation name, SOAP action and response element on this page is first party and verified. Code lists (product groups, product types, payment types, service codes, report ids) come from open source integrations that cite the Aramex manual page by page; they are marked medium confidence and should be checked against the manual once you have portal access.
What it is
Aramex is a logistics and transportation company founded in Amman, headquartered in Dubai and listed on the Dubai Financial Market. Its network is strongest across the Gulf Cooperation Council states, the Levant, North Africa and South Asia, with a global reach that leans on partners outside that core. It runs domestic express within several of those countries as well as international express, and it is a member of the Global Distribution Alliance.
For an Indian seller the shape of the opportunity is specific. Aramex is rarely the domestic carrier in India, where Delhivery, Blue Dart, Ecom Express and the rest dominate. It is the carrier a brand quotes for Gulf bound shipments, where it usually beats FedEx and DHL on price and often on transit time, and where it supports cash on delivery in markets where COD is still the norm. It is also the carrier of choice for Gulf based sellers shipping domestically, which is why almost every open source Aramex integration you will find is written for Saudi Arabia or the United Arab Emirates.
There is no marketplace and no catalogue here. One connection is one Aramex account number plus its entity code, and a brand with a separate domestic and international account will be two connections.
API access
There is no developer console and no self serve key. You get credentials from Aramex when you open an account, and you get six values rather than two:
Two further values travel with them: Version, conventionally v1 or v1.0, and Source, an integer that identifies the calling platform. Open source integrations consistently send Source: 24, which is the value Aramex assigns to third party integrations.
Aramex publishes a shared set of test credentials in its Shipping Services API manual, and the same values appear in dozens of public integrations: a testingapi@aramex.com user against account number 20016, entity AMM, country JO. Treat those as a smoke test target only. They are shared with the whole internet, their state is unpredictable, and several integration authors warn that debugging against them wastes time because the failure is often the account rather than the request. Ask Aramex for your own test account.
The API manual referenced throughout the open source ecosystem is at aramex.com/docs/default-source/resourses/resourcesdata/shipping-services-api-manual.pdf. It was not fetchable on 2026-09-21 (403), but its appendices are the authoritative source for the code lists quoted below.
There are no official Aramex SDKs. The ecosystem is entirely community built, and the maintained clients named in Sources are the practical reference.
Authentication
There is no token, no OAuth, no API key header and no session. Credentials are part of the request body of every operation. This is unusual enough to shape the connector design: the credential store has to hand six fields to every call rather than one bearer token, and there is nothing to refresh, rotate on a timer or cache.
Endpoints, verified from the live WSDLs:
Append ?singleWsdl to any of those for the WSDL, or ?wsdl for the multi part version. Append /json/<OperationName> for the JSON mirror.
Two test hosts are in circulation. ws.dev.aramex.net is the long standing one and appears in most integrations and in Aramex's own documentation references; ws.sbx.aramex.net appears in newer clients. Which one is live for a given account is not published anywhere reachable. Confirm with Aramex at onboarding rather than guessing, and build the host as configuration.
SOAP call
POST /ShippingAPI.V2/Tracking/Service_1_0.svc HTTP/1.1 Host: ws.aramex.net Content-Type: text/xml; charset=utf-8 SOAPAction: http://ws.aramex.net/ShippingAPI/v1/Service_1_0/TrackShipments
The SOAP action namespace is http://ws.aramex.net/ShippingAPI/v1/Service_1_0/ followed by the operation name, for every operation on every service.
JSON call
The same operation, same object graph, no envelope:
curl -X POST \
"https://ws.aramex.net/ShippingAPI.V2/Tracking/Service_1_0.svc/json/TrackShipments" \
-H "Content-Type: application/json" \
-d '{
"ClientInfo": {
"UserName": "api@example.com",
"Password": "REDACTED",
"AccountNumber": "20016",
"AccountPin": "331421",
"AccountEntity": "AMM",
"AccountCountryCode": "JO",
"Version": "v1.0",
"Source": 24
},
"Transaction": { "Reference1": "our-correlation-id" },
"Shipments": ["1234567890"],
"GetLastTrackingUpdateOnly": false
}'
Transaction is an optional envelope of five free text Reference1 to Reference5 fields that Aramex echoes back unchanged on the response. It is the correlation handle, since there is no request id header. Use it.
Objects we can read
Aramex is a carrier. Of the unified model objects only shipments is natively present. There are no orders, order items, products, listings, inventory, customers or settlements.
Orders
Not available. Order context reaches Aramex only as reference fields: Reference1, Reference2 and Reference3 on the shipment, plus Reference1 and Reference2 on the shipper and consignee parties. Those come back on the tracking result as ShipmentReference1, ShipperReference1, ShipperReference2, ConsigneeReference1 and ConsigneeReference2, so writing our order_id into Reference1 at ship time is what makes reconciliation possible later.
Shipments and tracking
The Tracking service exposes three operations, verified from the live WSDL:
TrackShipments takes Shipments, an array of waybill number strings, and a GetLastTrackingUpdateOnly boolean. Set it to false for our ingest: we want the whole history, not the latest line. There is no pagination and no date window; the unit of work is the list of waybills you pass.
The response shape is the thing to get right. TrackingResults is not an array. It is a serialised .NET dictionary mapping each waybill number to an array of TrackingResult records, which in JSON comes out as a list of { "Key": "...", "Value": [ ... ] } pairs. Unknown waybills come back separately in NonExistingWaybills.
{
"Transaction": { "Reference1": "our-correlation-id" },
"Notifications": [],
"HasErrors": false,
"NonExistingWaybills": ["9999999999"],
"TrackingResults": [
{
"Key": "1234567890",
"Value": [
{
"WaybillNumber": "1234567890",
"UpdateCode": "SH014",
"UpdateDescription": "Delivered",
"UpdateDateTime": "2026-09-18T14:22:00",
"UpdateLocation": "Dubai, United Arab Emirates",
"UpdateTimeZone": "GMT+4",
"Comments": "Received by: J. Smith",
"ProblemCode": "",
"GrossWeight": "1.5",
"ChargeableWeight": "2",
"WeightUnit": "KG",
"ShipmentReference1": "ORDER-20483739",
"ShipperReference1": "",
"ConsigneeReference1": "",
"ForeignHAWBNumber": ""
}
]
}
]
}
Notes for the ingest:
UpdateCodeis the scan code andUpdateDescriptionthe human text. Map onUpdateCode. Aramex codes are prefixed strings, and the full list is in the API manual appendix rather than in the WSDL.ProblemCodeis the closest Aramex gets to a structured exception reason, and it is empty on a clean scan. Populated values are what feed ourndr_reason. The code list is in the manual, not the WSDL.UpdateDateTimehas no offset baked in; the offset is in the separateUpdateTimeZonestring. Recombine them, and do not assume UTC.GrossWeightagainstChargeableWeightis the volumetric reweigh. When they differ, Aramex has rated on the higher one and the invoice will follow.HasErrorsandNotificationsare the envelope level result. AHasErrors: truewith aNotifications[]of{ Code, Message }is how Aramex reports a bad request, usually with HTTP 200. Do not treat a 200 as success. CheckHasErrorson every response from every operation.
Proof of delivery
Partial and indirect. There is no proof of delivery document endpoint in any of the four WSDLs. What you get is the recipient name in the Comments field of the delivery update, which is free text and not reliably parseable, plus HasShipmentBeenDelivered as a boolean. Signature images and electronic proof of delivery documents are not exposed by this API. If a merchant needs a signed proof of delivery, that is a portal download or an account manager conversation.
Rates and serviceability
The Rate Calculator service has two operations:
{
"ClientInfo": { "UserName": "api@example.com", "Password": "REDACTED", "AccountNumber": "20016", "AccountPin": "331421", "AccountEntity": "AMM", "AccountCountryCode": "JO", "Version": "v1.0", "Source": 24 },
"OriginAddress": { "City": "Mumbai", "CountryCode": "IN" },
"DestinationAddress": { "City": "Dubai", "CountryCode": "AE" },
"ShipmentDetails": {
"NumberOfPieces": 1,
"ActualWeight": { "Value": 1, "Unit": "KG" },
"ProductGroup": "EXP",
"ProductType": "PPX",
"PaymentType": "P"
},
"PreferredCurrencyCode": "USD"
}
The response carries TotalAmount as { CurrencyCode, Value }, a RateDetails breakdown with Amount, OtherAmount1 through OtherAmount5, TotalAmountBeforeTax and TaxAmount, and an AdditionalCharges[] array of { Code, Amount }, alongside the usual HasErrors and Notifications.
There is no transit time in the rate response. Aramex does not publish an estimated delivery date through this API at all, which is a real gap against FedEx, UPS and DHL: if a merchant wants to show a delivery promise, we have to model it ourselves from historical UpdateDateTime data.
Serviceability is answered by the Location service rather than by the rate call:
FetchCities with a country code and a NameStartsWith prefix is the practical way to build an autocomplete, and IsAddressServiced is the one to call before accepting an order for a marginal destination.
Pickup
Pickup lives on the Shipping service, not on its own:
The create response is ProcessedPickup with an ID, a GUID, Reference1 and Reference2, and a ProcessedShipments array linking the shipments attached to that pickup. The GUID is the handle: CancelPickup takes the GUID and a comment. Store the GUID against the shipment or the cancel path is lost.
Returns and cancellations
Thin. There is no return object and no return label operation in the Shipping WSDL. A return is modelled as a new shipment in the reverse direction with the consignee and shipper swapped, and the FRDM free domicile service code where the original shipper pays. HoldShipments will stop a shipment in the network, which is the nearest thing to an RTO trigger, and ScheduleDelivery reschedules a failed attempt.
There is no NDR object. A failed attempt is a tracking update with a populated ProblemCode and an UpdateCode that the manual's appendix maps to an exception. RTO is a separate waybill moving the other way. Both have to be derived from the update history.
Payments and settlements
Not available. Cash on delivery is configured on the way out: the CODS service code on Details.Services, with CashOnDeliveryAmount as { CurrencyCode, Value } and optional CashAdditionalAmount and CollectAmount fields on the shipment. But there is no COD remittance API, and nothing in any WSDL reports money collected or remitted. In Gulf markets where COD is a large share of orders that is a significant gap: reconciliation is a finance file exercise with the Aramex account team.
The label report id interacts with COD and it is easy to get wrong. Integrations that cite the Aramex manual report two values for LabelInfo.ReportID: 9201 for a standard label and 9729 when the shipment carries cash on delivery, because 9201 with COD is rejected. LabelInfo.ReportType takes URL to receive a hosted PDF link in ShipmentLabel.LabelURL, or RPT to receive a streamed file in ShipmentLabel.LabelFileContents. Confidence on the specific report numbers is medium: they come from community integrations citing the manual, not from a page we could read.
Customers, products, listings, inventory, locations
Not applicable. The only location concept is Aramex's own network, through FetchOffices and FetchDropOffLocations. Those are not seller warehouses.
Writing back: listings, price and stock
Not applicable, this is a carrier. There are no listings, prices or stock levels at Aramex and nothing here writes to a sales channel. The write path is shipment lifecycle.
The Shipping service exposes eleven operations, verified from the live production WSDL on 2026-09-21:
Create a shipment
CreateShipments takes a Shipments[] array, so one call can create many. Each element carries Shipper, Consignee, optional ThirdParty, Reference1 to Reference3, ShippingDateTime, DueDate, Comments, Attachments[] and a Details block.
{
"ClientInfo": { "UserName": "api@example.com", "Password": "REDACTED", "AccountNumber": "20016", "AccountPin": "331421", "AccountEntity": "AMM", "AccountCountryCode": "JO", "Version": "v1.0", "Source": 24 },
"Transaction": { "Reference1": "our-correlation-id" },
"LabelInfo": { "ReportID": 9201, "ReportType": "URL" },
"Shipments": [
{
"Reference1": "ORDER-20483739",
"Shipper": {
"AccountNumber": "20016",
"PartyAddress": { "Line1": "Unit 4, Andheri East", "City": "Mumbai", "CountryCode": "IN" },
"Contact": {
"PersonName": "Acme Brands",
"CompanyName": "Acme Brands Pvt Ltd",
"PhoneNumber1": "912212345678",
"CellPhone": "919812345678",
"EmailAddress": "ops@example.com"
}
},
"Consignee": {
"PartyAddress": { "Line1": "Al Barsha 1", "City": "Dubai", "CountryCode": "AE" },
"Contact": {
"PersonName": "Jane Smith",
"PhoneNumber1": "97141234567",
"CellPhone": "971501234567",
"EmailAddress": "customer@example.com"
}
},
"ShippingDateTime": "2026-09-21T10:00:00",
"Details": {
"NumberOfPieces": 1,
"ActualWeight": { "Value": 1, "Unit": "KG" },
"ProductGroup": "EXP",
"ProductType": "PPX",
"PaymentType": "P",
"DescriptionOfGoods": "Cosmetics",
"GoodsOriginCountry": "IN",
"CustomsValueAmount": { "CurrencyCode": "USD", "Value": 40 },
"Services": "CODS",
"CashOnDeliveryAmount": { "CurrencyCode": "AED", "Value": 150 }
}
}
]
}
The response is a Shipments[] array of ProcessedShipment:
{
"Transaction": { "Reference1": "our-correlation-id" },
"Notifications": [],
"HasErrors": false,
"Shipments": [
{
"ID": "1234567890",
"Reference1": "ORDER-20483739",
"Reference2": "",
"Reference3": "",
"ForeignHAWB": "",
"HasErrors": false,
"Notifications": [],
"SortCode": "DXB/DXB",
"ShipmentLabel": {
"LabelURL": "https://ws.aramex.net/.../label.pdf",
"LabelFileContents": null
},
"ShipmentDetails": { "Origin": "BOM", "Destination": "DXB", "ChargeableWeight": 1 },
"ShipmentAttachments": []
}
]
}
ID is the AWB number. Note the two levels of error reporting: an envelope level HasErrors and Notifications, and a per shipment HasErrors and Notifications inside each ProcessedShipment. A batch of ten can be nine successes and one failure inside a single HTTP 200, so check both levels.
ShipmentLabel carries either LabelURL or LabelFileContents depending on LabelInfo.ReportType. Download and store the label rather than persisting the URL: hosted label links are not guaranteed to outlive the shipment.
Code lists
From the Aramex Shipping Services API manual appendices, as cited by maintained open source integrations. Medium confidence, verify against the manual.
Reserve waybill numbers
ReserveShipmentNumberRange pre-allocates a block of AWB numbers, and GetLastShipmentsNumbersRange reads back the last block issued. This matters for high volume operations that want to print labels offline or assign an AWB at order time rather than at ship time. If we adopt it, the reserved range has to be persisted and consumed carefully, because a reserved number that is never used is a gap Aramex will ask about.
Webhooks and notifications
There are none. None of the four WSDLs defines a callback, a subscription or a push operation. The word Notification in Aramex's schema means something entirely different: an ArrayOfNotification of { Code, Message } pairs returned inline on a response to report errors and warnings. It is not a subscription mechanism and nothing about it reaches our server unprompted.
So the ingest is a poll:
- Call
TrackShipmentswithGetLastTrackingUpdateOnly: false, batching open waybills per call. The WSDL does not cap theShipmentsarray, so establish a safe batch size empirically and keep it modest, in the region of 20 to 50 waybills, rather than assuming unlimited. - Cadence by shipment age: every 2 to 4 hours in transit, hourly around the expected delivery window, then stop once a terminal
UpdateCodeis seen. - De-duplicate on the tuple of waybill number,
UpdateDateTime,UpdateCodeandUpdateLocation, because the entire history is returned on every call. - Use
HasShipmentBeenDeliveredas a cheap closing check on shipments you only need a yes or no for, and reserve the fullTrackShipmentscall for shipments whose history we are actually storing. NonExistingWaybillson the response is how a freshly created AWB that has not yet scanned will come back. Do not treat it as a permanent failure for the first day or so.
If push is ever needed, it is an Aramex account manager conversation about a bespoke feed, not a self serve feature. Treat "Aramex has webhooks" as unverified and low confidence.
Rate limits and pagination
Aramex publishes no rate limits on any source reachable without portal access, and there are no quota headers in the WSDL responses.
Practical guidance: keep concurrency low and batches modest, because this is a WCF service rather than a modern gateway and the historical failure mode is slow responses under load rather than a clean 429. Set an explicit client timeout, because the maintained SDKs default to 30 seconds and the service can exceed it. Retry on transport failures only, never on a HasErrors: true, which is a deterministic business rejection that will fail identically on retry.
Ask Aramex for the published transactions per second and daily ceiling before going live at volume.
Mapping to the unified model
Aramex populates shipments and nothing else.
Gaps and open questions
- No rate limits published. Get the transactions per second and daily ceiling from Aramex before designing a polling schedule for a large book of shipments.
- No webhooks. Confirm with an account manager whether any push feed exists commercially. Until then the connector is poll only.
- No estimated delivery date anywhere in the API. Unlike every other carrier on this catalogue, Aramex returns no transit time with a rate and no expected delivery date on a track result. If a delivery promise is a product requirement, we have to model it from our own historical data.
- No proof of delivery document or signature image. Only a recipient name buried in free text
Comments. Confirm whether an electronic proof of delivery is available through the Aramex portal or a separate service. - No COD remittance reporting, which matters more here than for the other carriers because COD is a large share of Gulf volume. Establish the reconciliation file format with the account team.
- Code lists are second hand. Product types, payment options, service codes, problem codes, update codes and label report ids all come from the API manual, which was not fetchable. Get the current manual through the portal and diff it against the table above before writing the mapping layer.
- Two test hosts.
ws.dev.aramex.netandws.sbx.aramex.netboth appear in production quality integrations. Confirm which applies to our account. - Batch limits are unknown on
TrackShipmentsandCreateShipments. Establish them empirically in the test environment before sizing the ingest. - India specifics unverified. Which product types are available on an India origin account, and whether Aramex India issues API credentials on the same terms as Gulf entities, could not be checked. Confirm locally.
Sources
- Live Aramex production WSDLs, fetched and parsed on 2026-09-21. These are first party and supplied every operation name, SOAP action and response element on this page:
- Shipping Service WSDL (eleven operations,
ProcessedShipment,ShipmentLabel,ProcessedPickup) - Tracking Service WSDL (
TrackShipments,TrackPickup,HasShipmentBeenDelivered, theTrackingResultsdictionary and theTrackingResultelement list) - Rate Calculator WSDL (
CalculateRate,CalculateMultiRate,TotalAmount,RateDetails,AdditionalCharges) - Location Service WSDL (eight operations including
IsAddressServicedandFetchDropOffLocations)
- Shipping Service WSDL (eleven operations,
- Aramex Developers Solutions Center (403 to an unauthenticated fetcher on 2026-09-21) and the Shipping Services API manual at
aramex.com/docs/default-source/resourses/resourcesdata/shipping-services-api-manual.pdf(403 on 2026-09-21), which is the authoritative source for the code list appendices - Kareem-3del/aramex-sdk, a maintained TypeScript SDK bundling the four WSDLs, which supplied the
ClientInfofield set, theSource: 24convention, the production and sandbox host pairs and the tracking type definitions - Moustafa22/Laravel-Aramex-SDK, whose configuration file documents the product group, product type, payment type, payment option, service code and label report id lists with page references into the Aramex manual
- MakiOmar/Aramex-Woocommerce-api-integration, a WooCommerce integration whose testing guide confirms the
/jsonendpoint pattern and thews.dev.aramex.nettest host